Skip to content

⚡️ Faster fc.entityGraph on generate#7045

Merged
dubzzz merged 2 commits into
mainfrom
claude/perf-entityGraph-skip-draft-clone
Jun 11, 2026
Merged

⚡️ Faster fc.entityGraph on generate#7045
dubzzz merged 2 commits into
mainfrom
claude/perf-entityGraph-skip-draft-clone

Conversation

@dubzzz

@dubzzz dubzzz commented Jun 4, 2026

Copy link
Copy Markdown
Owner

Description

AI-agent disclosure: this PR was authored by an automated agent (Claude Code) and has not been line-by-line reviewed by a human before submission.

This is a performance-only change to fc.entityGraph. Generated values (graph topology and entity data) are unchanged — only the speed of generate improves. No public API change, no behavior change for end users. entityGraph is by far the most expensive arbitrary in the suite, so this is a welcome reduction in per-generate cost.

Measured improvement (interleaved separate-process A/B, median of medians):

  • entityGraph({ node: { id: integer() } }, { node: { linkTo: { arity: 'many', type: 'node' } } }): ~−8% ns/op (≈75.3 → ≈69.1 µs/op).
  • The docstring employee/team schema (0-1 manager, 1 team): ~−13% ns/op (≈47.5 → ≈41.3 µs/op).

Why

buildEntityStepArbitrary called draftNextProductionState(lastState) once purely to read the current entity (getCurrentEntity()) and the per-type existing counts (getExistingEntityCount(targetType)), and then called it a second time inside .map to perform the actual mutation. That first call is wasted work: it allocates a full clone of the produced-links state (Object.assign(Object.create(null), …)) plus several closures, all immediately discarded. chainUntil invokes this once per produced entity (~100× per construction), so it sits squarely on the hot path.

The two values it read are trivially derivable from lastState without any allocation:

  • current entity = lastState.toBeProducedEntities[lastState.nextIndex];
  • existing count = lastState.producedLinks[targetType].length — the freshly-drafted state has not enqueued anything yet, so the lengths are identical (verified, see below).

So the preparation phase now reads those directly, and the mutable draft is built lazily only inside the .map where the real mutation happens. While there, this also removes a dead countsInTargetType object that was populated but never read, and the two now-unused getter closures on the draft object (fewer closures allocated per remaining step).

Scope, correctness and impact

  • Impact: patch. A changeset (fast-check: patch, ⚡️ Faster fc.entityGraph on generate) is included.
  • Single concern: one file (OnTheFlyLinksForEntityGraphArbitrary.ts) plus the changeset.
  • Tests: the entityGraph integration spec and the internal _internals specs (OnTheFlyLinks, UnlinkedToLinkedEntities, InitialPool, UnlinkedEntities) all pass, and the full suite is green. Output was additionally checked to be structurally identical to main (800 generations, 0 fingerprint mismatches), so the eliminated call provably only read values equal to the direct reads — no new test is needed because the distribution is unchanged. The removed getters had no other callers (grep-confirmed, including tests).

Checklist

Don't delete this checklist and make sure you do the following before opening the PR

  • I have a full understanding of every line in this PR — whether the code was hand-written, AI-generated, copied from external sources or produced by any other tool
  • I flagged the impact of my change (minor / patch / major) either by running pnpm run bump or by following the instructions from the changeset bot
  • I kept this PR focused on a single concern and did not bundle unrelated changes
  • I followed the gitmoji specification for the name of the PR, including the package scope (e.g. 🐛(vitest) Something...) when the change targets a package other than fast-check
  • I added relevant tests and they would have failed without my PR (when applicable)

Generated by Claude Code

`buildEntityStepArbitrary` called `draftNextProductionState(lastState)`
once purely to read the current entity and the per-type existing counts,
then called it again inside `.map` to do the real mutation. The first
call is wasted work: it allocates a full clone of the produced-links
state plus several closures, all immediately discarded. `chainUntil`
runs this per entity (~100x per construction), so it is hot.

Read the two needed values directly instead — the current entity is
`lastState.toBeProducedEntities[lastState.nextIndex]` and the existing
count is `lastState.producedLinks[targetType].length` (the fresh draft
has not enqueued anything yet, so the lengths are identical). The
mutable draft is now built lazily, only inside the `.map`. Also drops a
dead `countsInTargetType` object that was populated but never read and
the two now-unused getter closures. Generated values are unchanged.

https://claude.ai/code/session_01SRx4yxfDXbBWd5JDy7nrtz
@changeset-bot

changeset-bot Bot commented Jun 4, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f299afe

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
fast-check Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jun 4, 2026

Copy link
Copy Markdown
@fast-check/ava

npm i https://pkg.pr.new/@fast-check/ava@7045

fast-check

npm i https://pkg.pr.new/fast-check@7045

@fast-check/jest

npm i https://pkg.pr.new/@fast-check/jest@7045

@fast-check/packaged

npm i https://pkg.pr.new/@fast-check/packaged@7045

@fast-check/poisoning

npm i https://pkg.pr.new/@fast-check/poisoning@7045

@fast-check/vitest

npm i https://pkg.pr.new/@fast-check/vitest@7045

@fast-check/worker

npm i https://pkg.pr.new/@fast-check/worker@7045

commit: f299afe

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

⏱️ Benchmark Results

Click to expand

 RUN  v4.1.5 /home/runner/work/fast-check/fast-check


 ✓  fast-check  test/bench/arbitraries.bench.ts > generate 25884ms
     name                                                      hz      min      max     mean      p75      p99     p995     p999     rme  samples
   · boolean()                                          14,196.24   0.0669   0.4211   0.0704   0.0694   0.0874   0.0994   0.2952  ±0.42%     7099  [1.04x] ⇑
     boolean()                                          13,705.03   0.0657   3.5792   0.0730   0.0677   0.2113   0.2334   0.3178  ±1.77%     6853  (baseline)
   · integer()                                          10,426.08   0.0860   0.4729   0.0959   0.0937   0.1480   0.1562   0.2272  ±0.43%     5214  [0.97x] ⇓
     integer()                                          10,715.14   0.0860   0.4511   0.0933   0.0929   0.1147   0.1260   0.2313  ±0.30%     5358  (baseline)
   · maxSafeInteger()                                    7,758.69   0.1174   0.5691   0.1289   0.1279   0.1576   0.1941   0.4096  ±0.38%     3880  [1.01x] ⇑
     maxSafeInteger()                                    7,700.26   0.1238   0.4996   0.1299   0.1276   0.1873   0.1965   0.3737  ±0.36%     3851  (baseline)
   · bigInt()                                            1,314.96   0.7017   1.1837   0.7605   0.7599   0.9980   1.0184   1.1837  ±0.56%      658  [0.95x] ⇓
     bigInt()                                            1,381.77   0.6889   1.3453   0.7237   0.7245   0.9167   1.0578   1.3453  ±0.45%      691  (baseline)
   · float()                                             6,314.17   0.1441   1.4489   0.1584   0.1565   0.2411   0.2438   0.4283  ±0.75%     3158  [0.96x] ⇓
     float()                                             6,568.78   0.1430   0.5747   0.1522   0.1492   0.2388   0.2524   0.4162  ±0.46%     3285  (baseline)
   · double()                                            2,225.79   0.4202   0.8191   0.4493   0.4544   0.6675   0.7027   0.7604  ±0.41%     1113  [1.10x] ⇑
     double()                                            2,014.94   0.4660   1.2054   0.4963   0.4959   0.6960   0.7324   1.1654  ±0.58%     1008  (baseline)
   · date()                                              4,256.73   0.2250   0.6075   0.2349   0.2374   0.3699   0.3990   0.5556  ±0.45%     2129  [1.06x] ⇑
     date()                                              4,001.61   0.2420   0.6183   0.2499   0.2547   0.2861   0.3324   0.4862  ±0.31%     2001  (baseline)
   · string()                                            1,205.47   0.7716   1.3093   0.8296   0.8328   1.1169   1.1673   1.3093  ±0.52%      603  [1.02x] ⇑
     string()                                            1,179.59   0.7929   1.1707   0.8478   0.8522   1.0834   1.1288   1.1707  ±0.40%      590  (baseline)
   · string({ maxLength: 100, size: 'max' })               187.66   5.0046   5.9940   5.3287   5.4439   5.9940   5.9940   5.9940  ±0.69%       94  [0.98x] ⇓
     string({ maxLength: 100, size: 'max' })               190.56   4.9146   5.7090   5.2478   5.3227   5.7090   5.7090   5.7090  ±0.66%       96  (baseline)
   · string({ unit: 'grapheme' })                          762.81   1.2299   1.8842   1.3109   1.3208   1.6463   1.7452   1.8842  ±0.53%      382  [1.01x] ⇑
     string({ unit: 'grapheme' })                          757.34   1.2268   2.1252   1.3204   1.3230   1.7096   1.8275   2.1252  ±0.69%      379  (baseline)
   · base64String()                                      1,160.30   0.8068   1.3351   0.8618   0.8637   1.1787   1.2098   1.3351  ±0.53%      581  [1.02x] ⇑
     base64String()                                      1,139.34   0.8305   1.2166   0.8777   0.8821   1.1510   1.1777   1.2166  ±0.45%      570  (baseline)
   · array(integer())                                    2,160.83   0.4219   0.8838   0.4628   0.4652   0.7011   0.7261   0.8318  ±0.49%     1081  [1.02x] ⇑
     array(integer())                                    2,111.40   0.4383   0.8853   0.4736   0.4777   0.7000   0.7312   0.8822  ±0.46%     1056  (baseline)
   · array(integer(), { maxLength: 100, size: 'max' })     351.14   2.5122   3.7828   2.8479   2.8412   3.7411   3.7828   3.7828  ±1.50%      176  [0.98x] ⇓
     array(integer(), { maxLength: 100, size: 'max' })     356.54   2.5828   3.2151   2.8047   2.8339   3.1501   3.2151   3.2151  ±0.56%      179  (baseline)
   · uniqueArray(integer())                              1,439.19   0.6422   1.2008   0.6948   0.6991   0.9417   0.9869   1.2008  ±0.51%      720  [0.99x] ⇓
     uniqueArray(integer())                              1,459.75   0.6268   1.1608   0.6851   0.6879   0.9580   0.9941   1.1608  ±0.52%      730  (baseline)
   · set(integer())                                      1,133.21   0.8163   1.3508   0.8824   0.8848   1.1827   1.2583   1.3508  ±0.53%      567  [0.98x] ⇓
     set(integer())                                      1,155.10   0.7957   1.3289   0.8657   0.8696   1.1607   1.2049   1.3289  ±0.57%      578  (baseline)
   · tuple(integer())                                    5,755.52   0.1633   0.6080   0.1737   0.1720   0.2067   0.4017   0.4451  ±0.48%     2878  [0.96x] ⇓
     tuple(integer())                                    6,001.78   0.1564   0.5776   0.1666   0.1648   0.2134   0.4084   0.4571  ±0.52%     3001  (baseline)
   · record({ a: integer() })                            2,853.65   0.3360   0.7603   0.3504   0.3525   0.5807   0.5986   0.7411  ±0.48%     1427  [0.99x] ⇓
     record({ a: integer() })                            2,895.27   0.3307   0.7725   0.3454   0.3474   0.5838   0.6228   0.7613  ±0.50%     1448  (baseline)
   · dictionary(string(), integer())                       114.98   7.8881  12.2314   8.6972   8.7470  12.2314  12.2314  12.2314  ±2.42%       58  [1.03x] ⇑
     dictionary(string(), integer())                       112.04   8.0899  14.3480   8.9250   9.0384  14.3480  14.3480  14.3480  ±2.88%       57  (baseline)
   · map(string(), integer())                              188.72   4.8939   5.8622   5.2989   5.3685   5.8622   5.8622   5.8622  ±0.66%       95  [1.03x] ⇑
     map(string(), integer())                              182.70   5.1675   8.6430   5.4733   5.5141   8.6430   8.6430   8.6430  ±1.45%       92  (baseline)
   · constant(1)                                        29,623.15   0.0321   0.4693   0.0338   0.0333   0.0450   0.0487   0.2922  ±0.57%    14812  [1.02x] ⇑
     constant(1)                                        29,114.17   0.0327   0.4019   0.0343   0.0336   0.0498   0.0626   0.2064  ±0.44%    14558  (baseline)
   · constantFrom(1, 2)                                 13,298.30   0.0717   0.5845   0.0752   0.0743   0.0875   0.0966   0.3855  ±0.46%     6650  [0.98x] ⇓
     constantFrom(1, 2)                                 13,518.44   0.0711   0.4805   0.0740   0.0730   0.0872   0.0931   0.3535  ±0.42%     6760  (baseline)
   · oneof(integer(), integer())                         5,030.45   0.1677   1.9371   0.1988   0.2023   0.2816   0.2846   0.7985  ±1.11%     2516  [0.89x] ⇓
     oneof(integer(), integer())                         5,639.28   0.1692   0.6414   0.1773   0.1765   0.1955   0.2126   0.4993  ±0.39%     2820  (baseline)
   · oneof({ weight, arbitrary }, ...)                   5,559.04   0.1634   1.1425   0.1799   0.1749   0.2744   0.2790   0.5373  ±0.71%     2780  [0.96x] ⇓
     oneof({ weight, arbitrary }, ...)                   5,776.62   0.1643   0.5967   0.1731   0.1721   0.2003   0.2146   0.4898  ±0.39%     2889  (baseline)
   · option(integer())                                   6,101.04   0.1561   0.5946   0.1639   0.1623   0.1910   0.2069   0.5185  ±0.47%     3051  [1.02x] ⇑
     option(integer())                                   5,998.86   0.1581   0.6101   0.1667   0.1655   0.1859   0.2207   0.5052  ±0.46%     3000  (baseline)
   · subarray([1, 2, 3, 4, 5])                           2,435.09   0.3800   0.8327   0.4107   0.4101   0.6854   0.7011   0.8297  ±0.63%     1218  [1.08x] ⇑
     subarray([1, 2, 3, 4, 5])                           2,261.96   0.4111   0.8956   0.4421   0.4427   0.7241   0.7405   0.8740  ±0.57%     1131  (baseline)
   · letrec(tree)                                          566.79   1.4774   5.0323   1.7643   1.7201   4.9662   4.9902   5.0323  ±3.57%      284  [0.98x] ⇓
     letrec(tree)                                          576.30   1.4077   5.0876   1.7352   1.6864   4.8743   4.9776   5.0876  ±3.69%      290  (baseline)
   · memo(tree)                                            524.87   1.5036  15.4567   1.9052   1.7284   5.8279   6.2246  15.4567  ±7.14%      264  [0.93x] ⇓
     memo(tree)                                            563.21   1.4660   5.4340   1.7755   1.7107   5.1828   5.3028   5.4340  ±4.03%      282  (baseline)
   · anything()                                           74.8408  10.7620  28.4424  13.3617  13.8372  28.4424  28.4424  28.4424  ±8.03%       38  [0.93x] ⇓
     anything()                                           80.2196  10.9689  19.9417  12.4658  13.1173  19.9417  19.9417  19.9417  ±3.74%       41  (baseline)
   · json()                                               76.5354  11.4009  14.8307  13.0658  13.6421  14.8307  14.8307  14.8307  ±2.33%       39  [1.03x] ⇑
     json()                                               74.0003  12.3082  16.0017  13.5135  13.8402  16.0017  16.0017  16.0017  ±2.21%       38  (baseline)
   · entityGraph(node -> node)                            12.6362  75.2515  82.8432  79.1375  81.4264  82.8432  82.8432  82.8432  ±2.60%       10  [1.10x] ⇑
     entityGraph(node -> node)                            11.4481  79.9991   113.32  87.3506  86.6816   113.32   113.32   113.32  ±7.69%       10  (baseline)
   · emailAddress()                                       96.4201   9.5556  23.4985  10.3713   9.9880  23.4985  23.4985  23.4985  ±6.37%       49  [0.95x] ⇓
     emailAddress()                                        101.81   9.4061  10.1752   9.8224   9.9881  10.1752  10.1752  10.1752  ±0.55%       51  (baseline)
   · webUrl()                                              191.88   5.0227   5.7961   5.2116   5.2279   5.7961   5.7961   5.7961  ±0.52%       96  [0.99x] ⇓
     webUrl()                                              194.64   4.9520   5.5600   5.1376   5.1848   5.5600   5.5600   5.5600  ±0.53%       98  (baseline)
   · ipV4()                                              1,543.09   0.6265   1.0706   0.6480   0.6490   0.9145   0.9250   1.0706  ±0.38%      772  [1.01x] ⇑
     ipV4()                                              1,524.60   0.6347   1.1619   0.6559   0.6554   0.9723   0.9919   1.1619  ±0.46%      763  (baseline)
   · ipV6()                                                277.57   3.4616   4.0501   3.6027   3.6117   3.9986   4.0501   4.0501  ±0.54%      139  [1.04x] ⇑
     ipV6()                                                267.82   3.5510   5.5627   3.7338   3.7086   5.1555   5.5627   5.5627  ±1.20%      134  (baseline)
   · uuid()                                                795.31   1.2151   2.8406   1.2574   1.2417   1.8354   2.5009   2.8406  ±1.01%      398  [0.98x] ⇓
     uuid()                                                813.39   1.2009   1.6898   1.2294   1.2254   1.4957   1.5266   1.6898  ±0.41%      407  (baseline)
   · stringMatching(/^abc$/)                            28,083.73   0.0340   0.4064   0.0356   0.0351   0.0473   0.0541   0.2555  ±0.46%    14042  [1.00x] ⇓
     stringMatching(/^abc$/)                            28,215.74   0.0337   0.4152   0.0354   0.0349   0.0471   0.0523   0.2623  ±0.49%    14108  (baseline)
   · stringMatching(/^[a-zA-Z0-9]+$/)                      671.63   1.4190   1.9990   1.4889   1.4949   1.7973   1.8960   1.9990  ±0.50%      336  [0.98x] ⇓
     stringMatching(/^[a-zA-Z0-9]+$/)                      688.39   1.3645   1.9006   1.4527   1.4599   1.7219   1.8326   1.9006  ±0.44%      345  (baseline)
   · mixedCase(string())                                   603.96   1.5733   2.0891   1.6557   1.6598   1.9934   2.0292   2.0891  ±0.48%      302  [1.01x] ⇑
     mixedCase(string())                                   597.28   1.5848   1.9748   1.6742   1.6836   1.8812   1.9349   1.9748  ±0.33%      299  (baseline)
   · integer().map(value+1)                              8,039.62   0.1158   0.5728   0.1244   0.1236   0.1463   0.1594   0.3970  ±0.42%     4020  [0.97x] ⇓
     integer().map(value+1)                              8,298.13   0.1134   0.4283   0.1205   0.1200   0.1407   0.1539   0.3415  ±0.32%     4150  (baseline)
   · integer().chain(integer())                          3,587.18   0.2478   1.2208   0.2788   0.2640   0.6469   0.7145   0.8358  ±1.33%     1794  [0.94x] ⇓
     integer().chain(integer())                          3,835.92   0.2461   0.6635   0.2607   0.2610   0.4858   0.5015   0.6476  ±0.56%     1918  (baseline)
   · integer().filter(true)                              9,316.60   0.0999   0.6024   0.1073   0.1073   0.1214   0.1300   0.4185  ±0.36%     4659  [1.01x] ⇑
     integer().filter(true)                              9,232.12   0.1013   0.5297   0.1083   0.1081   0.1212   0.1291   0.3619  ±0.31%     4617  (baseline)

 ✓  fast-check  test/bench/runners.bench.ts > runner 2429ms
     name                                                     hz     min     max    mean     p75     p99    p995    p999     rme  samples
   · assert on sync predicate not returning anything   12,562.54  0.0762  0.3933  0.0796  0.0775  0.1570  0.2023  0.2777  ±0.45%     6282  [0.99x] ⇓
     assert on sync predicate not returning anything   12,721.92  0.0758  0.3011  0.0786  0.0768  0.1487  0.1631  0.1891  ±0.32%     6361  (baseline)
   · assert on sync predicate returning true           12,526.74  0.0760  0.3721  0.0798  0.0772  0.1586  0.1816  0.3133  ±0.48%     6264  [0.96x] ⇓
     assert on sync predicate returning true           13,088.30  0.0725  0.3254  0.0764  0.0744  0.1485  0.1676  0.2705  ±0.42%     6545  (baseline)
   · assert on async predicate not returning anything   8,534.82  0.1109  0.3146  0.1172  0.1135  0.2020  0.2099  0.2183  ±0.42%     4268  [0.99x] ⇓
     assert on async predicate not returning anything   8,624.89  0.1069  0.3126  0.1159  0.1125  0.1946  0.1990  0.2268  ±0.40%     4314  (baseline)
   · check on sync predicate not returning anything    12,401.56  0.0761  0.3887  0.0806  0.0775  0.1888  0.2066  0.2842  ±0.56%     6201  [0.95x] ⇓
     check on sync predicate not returning anything    13,049.94  0.0726  0.3249  0.0766  0.0747  0.1392  0.1586  0.2187  ±0.36%     6525  (baseline)

 BENCH  Summary

   fast-check  constant(1) - test/bench/arbitraries.bench.ts > generate
    1.05x faster than stringMatching(/^abc$/)
    2.09x faster than boolean()
    2.23x faster than constantFrom(1, 2)
    2.84x faster than integer()
    3.18x faster than integer().filter(true)
    3.68x faster than integer().map(value+1)
    3.82x faster than maxSafeInteger()
    4.69x faster than float()
    4.86x faster than option(integer())
    5.15x faster than tuple(integer())
    5.33x faster than oneof({ weight, arbitrary }, ...)
    5.89x faster than oneof(integer(), integer())
    6.96x faster than date()
    8.26x faster than integer().chain(integer())
    10.38x faster than record({ a: integer() })
    12.17x faster than subarray([1, 2, 3, 4, 5])
    13.31x faster than double()
    13.71x faster than array(integer())
    19.20x faster than ipV4()
    20.58x faster than uniqueArray(integer())
    22.53x faster than bigInt()
    24.57x faster than string()
    25.53x faster than base64String()
    26.14x faster than set(integer())
    37.25x faster than uuid()
    38.83x faster than string({ unit: 'grapheme' })
    44.11x faster than stringMatching(/^[a-zA-Z0-9]+$/)
    49.05x faster than mixedCase(string())
    52.26x faster than letrec(tree)
    56.44x faster than memo(tree)
    84.36x faster than array(integer(), { maxLength: 100, size: 'max' })
    106.72x faster than ipV6()
    154.38x faster than webUrl()
    156.97x faster than map(string(), integer())
    157.85x faster than string({ maxLength: 100, size: 'max' })
    257.64x faster than dictionary(string(), integer())
    307.23x faster than emailAddress()
    387.05x faster than json()
    395.82x faster than anything()
    2344.30x faster than entityGraph(node -> node)

   fast-check  assert on sync predicate not returning anything - test/bench/runners.bench.ts > runner
    1.00x faster than assert on sync predicate returning true
    1.01x faster than check on sync predicate not returning anything
    1.47x faster than assert on async predicate not returning anything

Benchmark report written to /home/runner/work/fast-check/fast-check/benchmark.json

Commit: f299afe (merge: 2ee092b)

@codecov

codecov Bot commented Jun 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.88%. Comparing base (dc9f32a) to head (f299afe).
⚠️ Report is 25 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7045      +/-   ##
==========================================
+ Coverage   94.86%   94.88%   +0.01%     
==========================================
  Files         212      212              
  Lines        5884     5943      +59     
  Branches     1543     1562      +19     
==========================================
+ Hits         5582     5639      +57     
- Misses        294      296       +2     
  Partials        8        8              
Flag Coverage Δ
tests 94.88% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dubzzz
dubzzz enabled auto-merge (squash) June 11, 2026 07:27
@dubzzz
dubzzz merged commit 38b9613 into main Jun 11, 2026
52 checks passed
@dubzzz
dubzzz deleted the claude/perf-entityGraph-skip-draft-clone branch June 11, 2026 07:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants