diff --git a/scripts/partition-test-shards.mjs b/scripts/partition-test-shards.mjs index d3757cbb9f4..3c2f37e3764 100644 --- a/scripts/partition-test-shards.mjs +++ b/scripts/partition-test-shards.mjs @@ -157,6 +157,14 @@ const TIMINGS_PATH = path.join(REPO_ROOT, 'scripts', 'test-shard-timings.json'); // beside them. That last figure is the floor this count cannot move: a CLI // slice (~960-1010s measured) is serial, so past eight the slowest shard is // the slice and more shards only add runners. +// +// ⚠ The bins above were placed by their SUM. Since #25870 partition() places +// them by that same wall model (WHOLE_LEG_PARALLELISM), so a slice shard no +// longer carries a whole-package leg ahead of its slice; on the committed +// dataset's full list the predicted steps move from 1277s on the three slice +// shards (643s elsewhere) to 966s on the slice shards and 830s elsewhere. On +// the 2026-10-26 refresh, with the CLI cut into 4 slices (pin 3c, below), all +// eight read ~738s. export const SHARD_COUNT = 8; // The acceptance bound #10472 set: the slowest shard within ~1.3x the mean. @@ -354,10 +362,23 @@ export function timingModeNote(event) { // n = 2 869.44s 1.52x still the floor // n = 3 579.63s 1.01x meets -- spec's task is the floor // -// So n = 3, and pin 3c holds it there. Slices are placed at their PLAIN weight -// (partition() is unchanged), so every bin keeps the density the whole-package +// So n = 3, and pin 3c held it there. Slices were placed at their PLAIN weight +// (partition() unchanged), so every bin kept the density the whole-package // split had -- see densityCap() for the hard limit on that and its pin. // +// RE-DERIVED AT 4 (#25870), on the 14-run refresh of 2026-10-26 (newest run +// 40272142430): the CLI at 2697.45s. `@objectstack/spec` (1168.98s) and +// `@objectstack/runtime` (793.70s) each run as two tasks, so the heaviest +// other serial task is `@objectstack/metadata-protocol`'s 670.12s, and a slice +// must sit within 1.3 x 670.12 = 871.16s. +// +// n = 3 899.15s 1.34x still the floor -- pin 3c refused 3 +// n = 4 674.36s 1.01x meets -- metadata-protocol is the floor +// +// Since #25870 partition() places a slice at its wall share rather than its +// plain weight (WHOLE_LEG_PARALLELISM); `total`, and so the density cap, still +// reads plain sums. +// // ⛔ THE COUNT IS CONFIGURED; WHETHER A RUN SLICES IS DECIDED BY THAT RUN. A // pull_request or merge_group run splits its own affected set, so planShards() // asks, of the run's own list, whether a configured package is that run's @@ -378,7 +399,7 @@ export function timingModeNote(event) { // a change to what that generator can DECODE, which is why the map it replaced // is kept below. export const FILE_SHARDED_PACKAGES = Object.freeze({ - '@objectstack/cli': 3, + '@objectstack/cli': 4, }); // THE MAP AS IT STOOD BEFORE ITS LAST CHANGE, read only by the generator's @@ -406,8 +427,10 @@ export const FILE_SHARDED_PACKAGES = Object.freeze({ // `test-core-run-summary-*`, #25771), so four days after that PR lands no // retained summary predates the change and this map decodes nothing. // The outgoing map of #22075's third round was empty -- the runs before it -// carried no slice -- so this one is empty too. -export const PREVIOUS_FILE_SHARDED_PACKAGES = Object.freeze({}); +// carried no slice. #25870 raised the CLI from 3 slices to 4, so this holds 3. +export const PREVIOUS_FILE_SHARDED_PACKAGES = Object.freeze({ + '@objectstack/cli': 3, +}); // The item grammar. A shard item is a package (`@objectstack/cli`) or a SLICE // of one (`@objectstack/cli 1/2`), and this pair of functions is the only place @@ -882,21 +905,58 @@ function readManifest(dir) { } } -// LPT greedy: heaviest package into the currently lightest bin. Deterministic: -// input order never matters because both the package sort and the bin choice -// break ties explicitly (by name / by lowest bin index). +// ── A SLICE IS A SERIAL LEG: BINS ARE PLACED BY WALL, NOT BY SUM (#25870) ──── +// +// A shard's "Run this shard's tests" step runs its whole packages four at a +// time (`--concurrency=4`) and THEN each file-level slice as a turbo run of its +// own, alone on the runner (ci.yml). So a slice's seconds reach the wall one for +// one while a whole package's are shared about 2.9 ways -- the wall model the +// SHARD_COUNT header calibrated (#25376): step ~ wholeSum / 2.9 + slice. This +// constant is that 2.9, not a new measurement. +// +// Placing bins by their SUM of seconds treated a slice second like a whole +// second, so every slice shard was filled up to the mean with whole packages and +// then ran its slice after them. On the committed dataset's full list that put +// ~900s of whole packages in front of each 966s CLI slice: predicted step 1277s +// on the three slice shards against 643s on the other five, and measured the +// same way on the pull_request runs #25870 tabulates -- 3/8-5/8 at 25-29 min, +// the rest at 7-17, the gap being each slice shard's whole-package leg +// (`Run this shard's tests` minus the slice leg's own turbo `Time:`). +// +// So partition() places by LOAD -- a bin's predicted wall, kept in whole-package +// seconds (a slice counts WHOLE_LEG_PARALLELISM times its weight) so that a list +// with no slice is placed by exactly the same additions and comparisons as the +// plain-sum LPT it replaced, byte for byte. `total` stays the plain sum of +// predicted test windows: the density cap and the drift report are statements +// about that quantity, and neither changes meaning here. +export const WHOLE_LEG_PARALLELISM = 2.9; + +// One item's share of a bin's load, in whole-package seconds. +export function loadOf(item) { + return item.slice ? item.weight * WHOLE_LEG_PARALLELISM : item.weight; +} + +// A bin's predicted `Run this shard's tests` step under the wall model. +export function wallOf(bin) { + return bin.load / WHOLE_LEG_PARALLELISM; +} + +// LPT greedy on load (above): heaviest item into the currently lightest bin. +// Deterministic: input order never matters because both the item sort and the +// bin choice break ties explicitly (by name / by lowest bin index). export function partition(items, shardCount) { const sorted = [...items].sort( - (a, b) => b.weight - a.weight || a.name.localeCompare(b.name, 'en') + (a, b) => loadOf(b) - loadOf(a) || a.name.localeCompare(b.name, 'en') ); - const bins = Array.from({ length: shardCount }, () => ({ total: 0, names: [] })); + const bins = Array.from({ length: shardCount }, () => ({ total: 0, load: 0, names: [] })); for (const it of sorted) { let best = 0; for (let i = 1; i < bins.length; i++) { - if (bins[i].total < bins[best].total) best = i; + if (bins[i].load < bins[best].load) best = i; } bins[best].names.push(it.name); bins[best].total += it.weight; + bins[best].load += loadOf(it); } return bins; } @@ -905,13 +965,34 @@ export function partition(items, shardCount) { // `floor` is the heaviest single package: sharding is BY PACKAGE, so no split // at any shard count can put max below it, and comparing it to the mean says // whether the bound is even reachable before anyone tries to reach it. +// +// `walls` / `wallRatio` are the same statistic on what the bins were placed by +// (wallOf, #25870). With no slice in the split they are the totals scaled by +// one constant, so the two ratios agree; with a slice, only the wall ratio says +// whether the shards finish together. A bin built by hand (no `load`) is read +// as all whole packages. export function balanceOf(bins, items = null) { const totals = bins.map((b) => b.total); const sum = totals.reduce((a, b) => a + b, 0); const mean = sum / bins.length; const max = Math.max(...totals); const floor = items ? Math.max(0, ...items.map((i) => i.weight)) : null; - return { totals, sum, mean, max, min: Math.min(...totals), ratio: mean === 0 ? 1 : max / mean, floor }; + const walls = bins.map((b) => wallOf({ load: b.load ?? b.total })); + const wallMean = walls.reduce((a, b) => a + b, 0) / bins.length; + const wallMax = Math.max(...walls); + return { + totals, + sum, + mean, + max, + min: Math.min(...totals), + ratio: mean === 0 ? 1 : max / mean, + floor, + walls, + wallMean, + wallMax, + wallRatio: wallMean === 0 ? 1 : wallMax / wallMean, + }; } // ── THE DENSITY CAP: NO SHARD CARRIES MORE THAN THE SPLIT PROVEN GREEN (#22075) ─ @@ -971,7 +1052,7 @@ export function refineToCap(bins, items, cap) { const weightOf = new Map(items.map((i) => [i.name, i.weight])); const slices = new Set(items.filter((i) => i.slice).map((i) => i.name)); const movable = (name) => !slices.has(name); - const out = bins.map((b) => ({ total: b.total, names: [...b.names] })); + const out = bins.map((b) => ({ total: b.total, load: b.load, names: [...b.names] })); const EPSILON = 1e-9; for (let step = 0; step < 10_000; step++) { let h = 0; @@ -998,15 +1079,21 @@ export function refineToCap(bins, items, cap) { } if (best === null) break; const { to, give, take } = best; + // Only whole packages move, and a whole package's load is its weight, so + // `load` follows `total` move for move. out[h].names.splice(out[h].names.indexOf(give), 1); out[h].total -= weightOf.get(give); + out[h].load -= weightOf.get(give); out[to].names.push(give); out[to].total += weightOf.get(give); + out[to].load += weightOf.get(give); if (take !== null) { out[to].names.splice(out[to].names.indexOf(take), 1); out[to].total -= weightOf.get(take); + out[to].load -= weightOf.get(take); out[h].names.push(take); out[h].total += weightOf.get(take); + out[h].load += weightOf.get(take); } } return out; @@ -1484,7 +1571,9 @@ const SELF_TEST_BATTERIES = Object.freeze({ // 8 of these 25 are pins 3b and 3c, the file-level slicing's (#16173), and // every one of them runs unconditionally: 3c's fixtures and 3b's cut of the // heaviest package do not depend on what the live map slices. - 'the balancing pins (#10472)': 25, + // 2 of these 27 are pin 2b, the wall placement's (#25870): a fixture, so it + // runs whatever the dataset holds. + 'the balancing pins (#10472)': 27, 'predicted-vs-measured drift (#16173)': 9, 'drift warning tier under the red (#16465)': 12, 'file-level slice items (#16173)': 20, @@ -1731,16 +1820,55 @@ function selfTest() { }); const real = datasetPlan.bins; const balance = balanceOf(real, datasetItems); + // Graded on predicted WALL, the quantity the bins are placed by (#25870): with + // a slice in the split, the bin SUMS are deliberately unequal -- a slice shard + // carries its serial slice and little else -- and only the walls say whether + // the shards finish together. With no slice the two ratios are the same number. check(() => { - if (balance.ratio > MAX_SHARD_OVER_MEAN) { + if (balance.wallRatio > MAX_SHARD_OVER_MEAN) { throw new Error( - `balance: at ${SHARD_COUNT} shards the heaviest bin is ${balance.ratio.toFixed(2)}x the mean ` + - `(${balance.max.toFixed(0)}s vs ${balance.mean.toFixed(0)}s), past the ${MAX_SHARD_OVER_MEAN}x bound. ` + - 'Bins: ' + balance.totals.map((t) => t.toFixed(0)).join('/') + 's.' + `balance: at ${SHARD_COUNT} shards the slowest predicted test step is ${balance.wallRatio.toFixed(2)}x the mean ` + + `(${balance.wallMax.toFixed(0)}s vs ${balance.wallMean.toFixed(0)}s), past the ${MAX_SHARD_OVER_MEAN}x bound. ` + + 'Walls: ' + balance.walls.map((t) => t.toFixed(0)).join('/') + 's; bins: ' + + balance.totals.map((t) => t.toFixed(0)).join('/') + 's.' ); } }); + // 2b. A SLICE IS PLACED AS THE SERIAL LEG IT IS (#25870). Three shards, a + // package cut in two (100s a slice) and three whole packages (100s, 50s, + // 50s). Placed by SUM -- the LPT this replaced -- each slice shard also + // takes a 50s whole package, which runs four-wide BEFORE the slice and + // lengthens that shard's step to ~117s. Placed by wall, the slices run + // alone and the three whole packages share the third shard (~69s). The + // two placements differ, so a revert to the sum reds here. + const serial = partition( + [ + { name: 's 1/2', weight: 100, slice: { index: 1, count: 2 } }, + { name: 's 2/2', weight: 100, slice: { index: 2, count: 2 } }, + mk('x', 100), + mk('y', 50), + mk('z', 50), + ], + 3 + ); + check(() => { + const crowded = serial.filter((bin) => bin.names.some((n) => n.startsWith('s ')) && bin.names.length > 1); + if (crowded.length > 0) { + throw new Error( + `slice placement: a slice shard also carries whole packages (${crowded.map((b) => b.names.join('+')).join('; ')}) ` + + 'that run before its serial slice -- are the bins placed by their plain SUM again?' + ); + } + }); + check(() => { + const walls = serial.map(wallOf); + const expected = [100, 100, 200 / WHOLE_LEG_PARALLELISM]; + if (walls.some((w, i) => Math.abs(w - expected[i]) > 1e-9)) { + throw new Error(`slice placement: predicted walls ${walls.map((w) => w.toFixed(2)).join('/')}s, expected ${expected.map((w) => w.toFixed(2)).join('/')}s`); + } + }); + // 3. The bound is REACHABLE at this shard count -- the arithmetic #10472 // asked about when it floated 6 -> 8. No split can put the heaviest bin // below the heaviest single package, so once that package exceeds @@ -3014,7 +3142,8 @@ function selfTest() { console.log( `partition-test-shards: self-test OK (${datasetPackages.length} measured packages ` + `-> ${datasetItems.length} shard items, ${SHARD_COUNT} shards, ` + - `max/mean ${balance.ratio.toFixed(2)}x <= ${MAX_SHARD_OVER_MEAN}x, floor ${balance.floor.toFixed(0)}s, ` + + `predicted test-step walls ${balance.walls.map((t) => t.toFixed(0)).join('/')}s, ` + + `max/mean ${balance.wallRatio.toFixed(2)}x <= ${MAX_SHARD_OVER_MEAN}x, floor ${balance.floor.toFixed(0)}s, ` + `bins ${balance.totals.map((t) => t.toFixed(2)).join('/')}s within the ${datasetCap.toFixed(2)}s density cap, ` + `file-level slices: ` + `${datasetPlan.decisions.filter((d) => d.count > 1).map((d) => `${d.name} x${d.count}`).join(', ') || 'none'})` @@ -3137,7 +3266,7 @@ function main() { { excluded } ); const mine = bins[shardIndex - 1]; - const { max, mean, ratio } = balanceOf(bins); + const { max, mean, ratio, walls, wallRatio } = balanceOf(bins); // Printed on every shard, not just the imbalanced one, and printed as the // RATIO the acceptance bound is written in: the per-shard numbers alone never // said whether the split was balanced, which is why #10472's imbalance had to @@ -3151,6 +3280,13 @@ function main() { `density cap ${cap.toFixed(2)}s; ` + `${packages - estimated} measured, ${estimated} estimated from test-file count)` ); + // What the bins were placed by (wallOf, #25870): the test step each shard is + // predicted to take, a slice counted as the serial leg it runs as. + console.error( + ` predicted test-step walls (whole / ${WHOLE_LEG_PARALLELISM} + slice): ` + + `${walls.map((w) => w.toFixed(0)).join('/')}s, this shard ${wallOf(mine).toFixed(0)}s; ` + + `max/mean ${wallRatio.toFixed(2)}x` + ); // Only a document that states its own slicing prints this, so a Test Core // shard's log is unchanged; the nightly's says where its slice count came from. if (acrossShards !== null) { diff --git a/scripts/test-shard-timings.json b/scripts/test-shard-timings.json index 946dd83387d..e68f9b230d5 100644 --- a/scripts/test-shard-timings.json +++ b/scripts/test-shard-timings.json @@ -1,192 +1,291 @@ { "note": "GENERATED by scripts/measure-test-shard-timings.mjs -- do not hand-edit. Per-package `turbo run test` durations in seconds, the balancing input for the Test Core shard split (scripts/partition-test-shards.mjs). See `provenance.refresh` to regenerate. Every weight is a real measurement: the ones in `carriedOver` were measured by an earlier refresh and re-confirmed unchanged by a turbo cache HIT in this one. A weight is the median of the executed runs that measured it; the ones in `provisional` rest on fewer than `provenance.minimumRuns` of them -- fit to balance on, NOT a baseline to set a ceiling from. `ceilings` is each package's suite-duration ceiling, graded by scripts/check-test-suite-ceilings.mjs: its slowest executed run in the refresh window that first set it, times `provenance.ceilingHeadroom`, then held by every later refresh -- raised only by a ruling, never by a refresh. `uncapped` names the packages with none, and why. `density` is the window's density reading: each run's count of executed packages (cache replays excluded) and each measured package's median share of its runs' executed seconds -- what the next refresh's diff judges a rise against.", "provenance": { - "measuredAt": "2026-10-23", + "measuredAt": "2026-10-26", "summaries": [ - "3L5pkkPHrqIIhRQweIZni3Jx7aO.json", - "3L5pK0YguKIvCY56IGYC68ubcnZ.json", - "3L5r7HrLBpJw06Kn9XvmCJKAk2I.json", - "3L5qPyNpntYIVqHv5kttg7ouTyb.json", - "3L5orAUkQaLbM91Eomq4Lp41E2I.json", - "3L5or8L4X8hDTrlB8fFYvDl14Nr.json", - "3L5p97SK55GLiCOyNWcQ0KPPYny.json", - "3L5pYfbQZQq7z6GuC4x4NEro8nt.json", - "3L5pYgQhfn9F1YfZWcZs3m75wLJ.json", - "3L5if5AHrl7wQgsMo3ih11gEmqi.json", - "3L5hSfDHmwBh5GMQNMGeg3mgpBD.json", - "3L5jEVrlkZ9AUR9obG1RxghGaNO.json", - "3L5jKNwhp3zxrgEkAdOEMu7HJiz.json", - "3L5ix9jJ5LfgjPDCVM23vrGANPf.json", - "3L5hYzIHzYbTnqZthz4E8Acoey6.json", - "3L5iwScsRQslaZqoufX9q49Ca1Y.json", - "3L5kHHjXj3jd2ikEXJkYAr2qoNg.json", - "3L5iMqqYvLtphnuVU2790j4BcOs.json", - "3L5aYyVM6hDZDXM2wUgLAzVn1lK.json", - "3L5b8ackq0B6vLxB1gJvGHvPwm5.json", - "3L5cwiNtOq0V3rj8Y3t0cpp099W.json", - "3L5a8o5LwuAyjA4N4ZHocot55Y2.json", - "3L5bCbVihHlFDbW27FNwV44BRAx.json", - "3L5dT9aCViSVhEDNf1glxKoUaPK.json", - "3L5aFXABy8dYjmenqLEja1JVybr.json", - "3L5dJx1cAfph7mWxor3zJT2UYI1.json", - "3L5bG4aQQV63WVrO3IpmJSur08r.json", - "3L5V0fYBXrPNFbEUIfP6XZ35QDi.json", - "3L5VJjjOdLIiHZSNqsrkIyYU9xA.json", - "3L5TjnxBup2JEvkC531UdO5iWTj.json", - "3L5VB2bblXMBlcCEImC68dliybU.json", - "3L5WEzoPTRwkpRiFoQ32OVzqO1V.json", - "3L5TzKPzELsixHpzSjlTIHpoU6f.json", - "3L5V6en0ePK8VGrYZov45WkLSaL.json", - "3L5U2MRXW2XALPTb0VzKo6dNFJg.json", - "3L5W57i8V6y1S6QzwcVd0yPwR0G.json", - "3L5NBqXWi7RH6wc1MHy717jo4b0.json", - "3L5P0U39kjIKstpb6wjyOjtmH5I.json", - "3L5ND5kM4oQJOYTfUJpDjFQKWsx.json", - "3L5NPoU7qJwhN7znV0srql9bw4Q.json", - "3L5NAdhsrWpMHqrza9YUkmWhbPd.json", - "3L5PSHkSEL8Qg8Njjjsdw2pz0hN.json", - "3L5NuylkQZ95nfitetQsSE4hvkk.json", - "3L5PkJwVZ43AQr28FfYYXyszhwu.json", - "3L5NeKyqy7O5jwElRRKlNYSJQv5.json", - "3L5FxoGDDW0aAns2yrHnVBLzzHa.json", - "3L5GofvOX3G4fWKovi2RjHNWRaB.json", - "3L5F4WWgME9vI6HK7iu0GBEJ0U9.json", - "3L5GDreVG7PT584aKMhIoEKLJFY.json", - "3L5FFQAu9qmm3VTgQbMZlSVvMY9.json", - "3L5HUQ5lfq5ym4mVY13SNNnFZ74.json", - "3L5Fd18OtpYfA89sDRpunV8qEgS.json", - "3L5ExCnfNxu0b2zJMAlU1NcsUqE.json", - "3L5GFbyUvTxjQxh2EUvxBQMxhbp.json", - "3L58EQzDDayMHI3g6DkmeodxKy9.json", - "3L57uQhzTpHqcPBN54RDFEET4Uz.json", - "3L59kg4N8hqgKoxz9cma89rnsGs.json", - "3L58xrCgLhQ3w6qiwBcLJsL4Gvc.json", - "3L57ykdu32hsG0CEyrpXurC33qg.json", - "3L5AHpdhkBPonHmH3q7y1nRYPZf.json", - "3L58JpBeQnSkG3glDgcCgs1Xgdd.json", - "3L59O1y0GZpYg2ai5VcbUHzqtVI.json", - "3L57nHTeD92ORte7cpJ1OIMS1rD.json", - "3L51mYL41RY1q8Er1eXMCmPjT7Z.json", - "3L52WQJ80eyu4PyyCTF9xfXd151.json", - "3L50glJH53t1JTZIQkxQFF0QpGB.json", - "3L51gYDjx9oKOgRqr3VI7MNogrX.json", - "3L52xWsBkNA851yAh8q1iograbK.json", - "3L50i4R33lk0o6XZ82F7WzPeQt1.json", - "3L51qEQLz6BJ1d9zlYXzqvlpo0O.json", - "3L50ngZJEiGlvN8YX4FuuAENKoF.json", - "3L52nHJeQYh3sAmrzVfKtD1vZqj.json" + "3LDaSZoydWFxKiH8lVKLKVxGaMJ.json", + "3LDaPIV2dIpgEvVGKFxYd6HvYkT.json", + "3LDaO15zRDYZSNL1mB4enxuV3pa.json", + "3LDaOA8UT8QuAmkEjdJ2ih9ciUl.json", + "3LDaO4ahLYajwSYg8Iy4e79uMZL.json", + "3LDaQTO1pa0xrf6skNVq1PTxAYj.json", + "3LDaQbbOFROA2if4SYKnPJnY8o6.json", + "3LDaNRvMdnlmDnRZo3E35ef7ks1.json", + "3LDaOeEKoicr9j7n9bhhFslV63z.json", + "3LDaRBIewlANXPlK3igFDETMWOI.json", + "3LDaRBTVuCafN7r6ZM5ZfFqjXx8.json", + "3LDUYCGqjs1sRzM1Hb1WD6PIwhN.json", + "3LDTsfHrAX3sOq0c6nnMHcuPx6Y.json", + "3LDTG0QWuTkpMMqTfVkFtgLyW0D.json", + "3LDTCt9nMnjs1OzDOslA4UsgCvu.json", + "3LDTD0OxpF7fQ5DdY8H1NtGZvFQ.json", + "3LDTbtbIiyRWaCz6X3v7kGwNVWQ.json", + "3LDVEm7r4dtDMAyjwMuVV0zmXc0.json", + "3LDTT8XKvxfOaZRj53OyH8xWSBF.json", + "3LDTFqIBMVBKsY28virwghMkFiL.json", + "3LDTKBXlf47dz3hfnKZMHkaTx9s.json", + "3LDTKLgrAjBCoXlvkdXVlk5d06g.json", + "3LDN6nIRzg0SK0Bfe5cFQYDpSGm.json", + "3LDMrn1JsFnStMbyMsWsjRCIppa.json", + "3LDM8vCv7eT8HJFiv6i1ba8F5C4.json", + "3LDM6YchNjUNnEX1mmCus3d5Lto.json", + "3LDM6XTlK0HzBh35UmBt3P9iTBG.json", + "3LDM5kcy0SUDC9jEeQmcPEihAji.json", + "3LDM5lyTXtiyMEprJRWvtNQhV6f.json", + "3LDMTBfery6kKunHMlt7Kd0szBw.json", + "3LDMAG5HG3glYUEjSdFbueF6BPE.json", + "3LDM7rqhvMfLuIe1brpwhqWirHV.json", + "3LDM7wRFUaB4zc3VwgshO1mBSCD.json", + "3LDGKabmuOiTpeutCfpQ8MCG3JL.json", + "3LDG0vuLgEd5aQwcBTlS0YBgnQp.json", + "3LDFJsWivFuJiiGHDEwILPwlcz4.json", + "3LDF8vkb02p6SNpuS4vKirjVwQ9.json", + "3LDF8xIQIUHmWeT9toL0o4jREsW.json", + "3LDFAqSn0y9wDS0lmJ1mYwamSPH.json", + "3LDFAs6AkJW4lWJOl3Pixh9EB4q.json", + "3LDFfH4jECaxoW15YV8XBjfpCwh.json", + "3LDFENmkz0oxlagjizS7tCB1mkd.json", + "3LDFGb6shtRRGKZE87sDkAOwhXb.json", + "3LDFGlhe5FUP6cAlO6a2rNhZ8Dv.json", + "3LCtwDL1RvwV3LsCCj5Pj7yN6Aj.json", + "3LCsVp9yNcuFTd4W1h2Uxny5Jpq.json", + "3LCsW62HFSmQutLoRc531TTmPmo.json", + "3LCv0vMFXsWiaOcjshFuUh0rweo.json", + "3LCtBosMSnAnSxYZxeaKp4puEo9.json", + "3LCsnLxYRS4BfVzGWACILMH0QlK.json", + "3LCtoOMEqIQZClJRjfIjl2WzvTV.json", + "3LCsTzeKKUrcWhmkhp5rXbFrmzq.json", + "3LCsSJDnOPW4vmOIKa580tpvczO.json", + "3LCv5DaXWaRqna0YqJzWSndYgGG.json", + "3LCsxEGt7TyrgdzwLBdNQnCj7ce.json", + "3LCmV3rMTs7wtFpTipqfnE0OTwk.json", + "3LClu2fJ5CL0KMrIF9NZxMsdHRA.json", + "3LClA8CyF7dJLIUAwrWJPMuolIP.json", + "3LCl9j2pcY0fUVyK6Mgwnt3B7v7.json", + "3LCl9deGxEkkmULZ5DvEM7f2dtP.json", + "3LClB22Q5pGTJNT4GhEhOfWBdNX.json", + "3LClB3eWfhAQUjsqZK8uibbrpyE.json", + "3LCl9LJwdmCIaWVwiKLHP7jtqMN.json", + "3LClHHXv8z3FYmPyqk1mKFNIXAg.json", + "3LCl8eYIdHlVT0ZItbe0UlbtmKO.json", + "3LCl8g0miILcr770UuUyGNaqfDw.json", + "3LCekjGcB6kfA0LBQVOtvZdyJwz.json", + "3LCeMJJubkzKlSLBUV4mhAw567n.json", + "3LCdsRub0h5xiZQTkx3HNCT1eqi.json", + "3LCdsCwP2A23ygiG4D3V2kJ9kAJ.json", + "3LCds6jOAUoZwUPIHDRnnmLkrBB.json", + "3LCdrA94CAIwysH3gLzmUkgtRah.json", + "3LCdrCFQYpMAaK0ABwdKmzlAQmt.json", + "3LCdteoI6PV9ApQpI9YjSyfPZQu.json", + "3LCdyf3bmXHqc8h0UPBDUd1LBem.json", + "3LCdw436KV0AeGSejShfHD60VZC.json", + "3LCdw6a1kqW9GzNKyNVvZI9rklg.json", + "3LCWX5J71I4rp7iKfQtsV5bOLx5.json", + "3LCWWsjoYHuNYKsj1F8SjA4HC9J.json", + "3LCWXBsBFOQkOVzU7fDlF49yEdg.json", + "3LCWX7QRGj9b82MbiyFv381x07W.json", + "3LCWXIsNky4qPD33mw15CaLU36t.json", + "3LCWYRaXK6Ypls3igfLhLxVp1hb.json", + "3LCWYKzowb5ktvobYfcml0W935G.json", + "3LCWYhVNJBuCoBVbca4apYB7XL8.json", + "3LCWY1xSWspaDuQAydMknIyP11C.json", + "3LCWW4w8notGugVkPyzBE8fDOUk.json", + "3LCWVzeqeINeG89tTqRZC0kEERu.json", + "3LCPFGjCJGDv96aKr0AsNKJS1ak.json", + "3LCPFUFYq2fszNDtFZn933fjTe8.json", + "3LCPFikJ4vlA9FrvABcM2utNGsq.json", + "3LCPFVLm15Tf6OeOwvceW9TLKA2.json", + "3LCPFPVv5NuabV7YPH5ZngI20ul.json", + "3LCPGsKYGTTKFwHqlRiNZtXDMxi.json", + "3LCPGv1syvP1CH86XNr33ZqPgpl.json", + "3LCPJvzLONBV1x8BfgA1YaLAVhw.json", + "3LCPFUCIBvdSaZ4qsQapAUMvKzF.json", + "3LCPEMxwnLKkKwpClLlXqmdrdiM.json", + "3LCPEO2ZWEPaxLnB4YUoHsdCUEx.json", + "3LCI0yuSEEwpDcv3mxTAabYsT74.json", + "3LCHzEibBmoaUQnasJ8dlmBXNAz.json", + "3LCI0Hyl8qxTnjCNL6h7ZVMlCeL.json", + "3LCHywitYKodFp5sSHabAXsUErB.json", + "3LCHz02JdnDgSLfiKj219achauU.json", + "3LCI1wF1e6DFIxxoIDxkGCMhjPm.json", + "3LCI225OECHtfdYnPG1stRhkS4A.json", + "3LCI1QxNYHbdkEVlUG1NauyzzdI.json", + "3LCI1euhgYjFncNbXEAZqLCJjbn.json", + "3LCI3DFmgnMsN5G68yfkOfWSZ0t.json", + "3LCI3CxQgQCISZCrV0Nn8ueHY5o.json", + "3LCC3rxx7LgNW7HKq0TrE4lZ3hI.json", + "3LCBbGH6vf6UKso8eF0icozaNYO.json", + "3LCAf6zNl797qrzrnaGUkv4tL7e.json", + "3LCBMyYBtLCSRYvfGYybeEZIkvw.json", + "3LCDD7DDnNUzbunqOjvBzfYzp5L.json", + "3LCAg06xKPufsgt8nyvIEo8DxlJ.json", + "3LCAg1BKIQRtwwOy5WWNJJ0UzVT.json", + "3LCAfNaWjSREo9QdnPSj2XBUUi9.json", + "3LCAftw6pqPiGQ2vIJPMyo1cofh.json", + "3LCAgTku9pHMsbPzXARi2V7Gx4E.json", + "3LCAgMRb0ZKJgXVwYr6hlUW0hi2.json", + "3LC4G3pPljtgnqvbMI7wHYweqU4.json", + "3LC42H4n3ghFeZGKSeBoXNEXeAC.json", + "3LC3LNHU6fXoQqP1Zrl9yWP3RvB.json", + "3LC409r9udvJ7ZqAjAe3rp1jfju.json", + "3LC5oojMAwIlwjm0nucDrW7IKOv.json", + "3LC3MIwksYBlx1BxAdaTMHrWb7E.json", + "3LC3MHdka4d4VTGwYcyF33J6EmL.json", + "3LC3LTCF4rRUyftjSLNmjjC3Bbd.json", + "3LC3M3tOMzsRJCJjXKKiXECiv29.json", + "3LC3KdDX3FsPzb5JXfKWmn49OuU.json", + "3LC3KgCkjiACXvOmaveS1ramgZH.json", + "3LBxXKoHflSvnVUxOGzmkfYAhxw.json", + "3LBxZjd6LkCX0hm3VHitN0bFbxh.json", + "3LBxQYi4KdBwoLjrfAW3Qc6sI9f.json", + "3LBxu3ApUnTrZtNTGTOrAYpgDgd.json", + "3LBwZxgStewMCWZB0DbJM5yDC97.json", + "3LByUkS0cMbQX3tuPekDh7yMrWX.json", + "3LBweyM37YiWR5BITbl8heAJ85y.json", + "3LBx52yfzG5egICSnFplmlhcos4.json", + "3LBxCCnd9t5oBDHOLDcuJPNgBsO.json", + "3LBwcOsrluJGy92YNKAfy93bM3N.json", + "3LByvd9eelZsmzimdQKpMx14Pjy.json", + "3LBpfnSHdoQPrufWbCIA3oYWMhQ.json", + "3LBpyRLEXr3FNvGPsV4K3NQi8ie.json", + "3LBq9Ly9kxM8spEL5Qpym9zUQqm.json", + "3LBrh12BGhRd1AdSpFfqp8sw995.json", + "3LBpdiEdj7OblBJgcg4Y4ZDIvCZ.json", + "3LBqeJD8XmRkGDPd746sMQZygSS.json", + "3LBpCjeKQnOUkJalK9527767wmB.json", + "3LBqAkoUaOrYcpfoMo2FCqzt9vK.json", + "3LBqehpRQHGFC6hD0t1tYbKjBAO.json", + "3LBpMqAuVndlJG2KRDjQN4Bv2WV.json", + "3LBrf9R97F4LvQJXKdxaKYDuLKM.json" ], "runs": [ - "39943147947", - "39936055900", - "39928834751", - "39921744055", - "39915751898", - "39909025131", - "39903431405", - "39898100438" + "40272142430", + "40266979145", + "40262173089", + "40257470166", + "40242835329", + "40238189261", + "40233481335", + "40228747755", + "40223991179", + "40219252911", + "40214410982", + "40209651657", + "40204927516", + "40200279306" ], "mergeRule": "median across runs; a file-sharded package is summed from its slices WITHIN one run first, and a run that cannot assemble every slice contributes no sample for it; a package not measured in this pass keeps its previous weight ONLY when a turbo cache HIT witnesses that its inputs are unchanged, and every such package is named in `carriedOver`", - "refresh": "node scripts/measure-test-shard-timings.mjs [--run ] ... --merge-into scripts/test-shard-timings.json --out scripts/test-shard-timings.json (summaries: the `test-core-run-summary--of-6` artifacts of any green run, or a local `pnpm exec turbo run test --concurrency=4 --summarize`. ⚠ ONE RUN COVERS ONLY 2-52 of ~71 packages depending on cache warmth, so feed SEVERAL runs -- a `--run ` before each run's summaries is REQUIRED, so a sliced package is assembled per run and then medianed like every other package -- and `--merge-into` to carry the cache-hit remainder. A package measured by fewer than `minimumRuns` executed runs is named in `provisional`, so feed runs until that list is empty. `.github/workflows/shard-timings-refresh.yml` does all of this weekly.)", + "refresh": "node scripts/measure-test-shard-timings.mjs [--run ] ... --merge-into scripts/test-shard-timings.json --out scripts/test-shard-timings.json (summaries: the `test-core-run-summary--of-` artifacts of any green run, or a local `pnpm exec turbo run test --concurrency=4 --summarize`. ⚠ ONE RUN COVERS ONLY 2-52 of ~71 packages depending on cache warmth, so feed SEVERAL runs -- a `--run ` before each run's summaries is REQUIRED, so a sliced package is assembled per run and then medianed like every other package -- and `--merge-into` to carry the cache-hit remainder. A package measured by fewer than `minimumRuns` executed runs is named in `provisional`, so feed runs until that list is empty. `.github/workflows/shard-timings-refresh.yml` does all of this weekly.)", "minimumRuns": 3, "ceilingHeadroom": 1.25 }, - "secondsPerTestFileFallback": 3.244, + "secondsPerTestFileFallback": 2.114, "packages": { - "@objectstack/cli": 2899.02, - "@objectstack/client": 147.21, - "@objectstack/client-react": 12.44, - "@objectstack/cloud-connection": 268.04, - "@objectstack/connector-imap": 3.67, - "@objectstack/connector-mcp": 43.15, - "@objectstack/connector-openapi": 33.96, - "@objectstack/connector-rest": 34.78, - "@objectstack/connector-slack": 34.99, - "@objectstack/core": 164.54, - "@objectstack/downstream-contract": 16.85, - "@objectstack/driver-memory": 141.51, - "@objectstack/driver-mongodb": 100, - "@objectstack/driver-sql": 384.28, - "@objectstack/driver-sqlite-wasm": 85.63, - "@objectstack/driver-turso": 189.07, - "@objectstack/embedder-openai": 5.56, - "@objectstack/example-crm": 41.32, - "@objectstack/example-embed-objectql": 28.22, - "@objectstack/example-showcase": 130.48, - "@objectstack/example-todo": 58.58, - "@objectstack/formula": 39.65, - "@objectstack/hono": 41.55, - "@objectstack/http-conformance": 125.37, - "@objectstack/knowledge-memory": 3.94, - "@objectstack/knowledge-ragflow": 4.23, - "@objectstack/lint": 200.52, - "@objectstack/mcp": 112.36, - "@objectstack/metadata": 119.96, - "@objectstack/metadata-core": 25.61, - "@objectstack/metadata-fs": 37.42, - "@objectstack/metadata-protocol": 629.62, - "@objectstack/objectql": 970.12, - "@objectstack/observability": 2.89, - "@objectstack/organizations": 73.2, - "@objectstack/platform-objects": 123.56, - "@objectstack/plugin-approvals": 360.06, - "@objectstack/plugin-audit": 249.24, - "@objectstack/plugin-auth": 405.25, - "@objectstack/plugin-dev": 50.78, - "@objectstack/plugin-email": 119.76, - "@objectstack/plugin-hono-server": 77.51, - "@objectstack/plugin-pinyin-search": 37.94, - "@objectstack/plugin-security": 360.02, - "@objectstack/plugin-sharing": 209.26, - "@objectstack/plugin-webhooks": 94.12, - "@objectstack/rest": 876.56, - "@objectstack/runtime": 848.96, - "@objectstack/sdui-parser": 4.23, - "@objectstack/service-analytics": 412.58, - "@objectstack/service-automation": 450.63, - "@objectstack/service-cache": 1.64, - "@objectstack/service-cluster": 21.59, - "@objectstack/service-cluster-redis": 22.41, - "@objectstack/service-datasource": 128.92, - "@objectstack/service-i18n": 17.69, - "@objectstack/service-job": 31.65, - "@objectstack/service-knowledge": 28.49, - "@objectstack/service-mailbox": 57.26, - "@objectstack/service-messaging": 158.74, - "@objectstack/service-package": 51.92, - "@objectstack/service-print": 32.82, - "@objectstack/service-queue": 36.08, - "@objectstack/service-realtime": 9.31, - "@objectstack/service-settings": 149.93, - "@objectstack/service-sms": 22.13, - "@objectstack/service-storage": 223.46, - "@objectstack/spec": 1606.55, - "@objectstack/trigger-api": 14.65, - "@objectstack/trigger-record-change": 81.69, - "@objectstack/trigger-schedule": 43.22, - "@objectstack/types": 23.67, - "@objectstack/verify": 220.52, - "@objectstack/vitest-filter-preflight": 28.34, - "create-objectstack": 26.36 + "@objectstack/cli": 2697.45, + "@objectstack/client": 81.49, + "@objectstack/client-react": 8.1, + "@objectstack/cloud-connection": 115.93, + "@objectstack/connector-imap": 3.55, + "@objectstack/connector-mcp": 29.9, + "@objectstack/connector-openapi": 24.54, + "@objectstack/connector-rest": 28.39, + "@objectstack/connector-slack": 23.67, + "@objectstack/core": 103.58, + "@objectstack/downstream-contract": 6.8, + "@objectstack/driver-memory": 103.22, + "@objectstack/driver-mongodb": 54.92, + "@objectstack/driver-sql": 241.07, + "@objectstack/driver-sqlite-wasm": 63.75, + "@objectstack/driver-turso": 129.29, + "@objectstack/embedder-openai": 5.22, + "@objectstack/example-crm": 23.11, + "@objectstack/example-embed-objectql": 7.86, + "@objectstack/example-showcase": 48.49, + "@objectstack/example-todo": 27.48, + "@objectstack/formula": 39.47, + "@objectstack/hono": 30.38, + "@objectstack/http-conformance": 155.47, + "@objectstack/knowledge-memory": 2.57, + "@objectstack/knowledge-ragflow": 4.29, + "@objectstack/lint": 141.56, + "@objectstack/mcp": 68.77, + "@objectstack/metadata": 142.75, + "@objectstack/metadata-core": 15.7, + "@objectstack/metadata-fs": 21.58, + "@objectstack/metadata-protocol": 670.12, + "@objectstack/objectql": 450.03, + "@objectstack/observability": 3.06, + "@objectstack/organizations": 99.66, + "@objectstack/platform-objects": 80.46, + "@objectstack/plugin-approvals": 254.27, + "@objectstack/plugin-audit": 255.86, + "@objectstack/plugin-auth": 283.83, + "@objectstack/plugin-dev": 48.97, + "@objectstack/plugin-email": 77.36, + "@objectstack/plugin-hono-server": 68.19, + "@objectstack/plugin-pinyin-search": 53.27, + "@objectstack/plugin-security": 245.56, + "@objectstack/plugin-sharing": 150.16, + "@objectstack/plugin-webhooks": 49.65, + "@objectstack/rest": 569.96, + "@objectstack/runtime": 793.7, + "@objectstack/sdui-parser": 3.68, + "@objectstack/service-analytics": 406.18, + "@objectstack/service-automation": 522.93, + "@objectstack/service-cache": 2.22, + "@objectstack/service-cluster": 11.41, + "@objectstack/service-cluster-redis": 12.79, + "@objectstack/service-datasource": 90.24, + "@objectstack/service-i18n": 7.81, + "@objectstack/service-job": 14.25, + "@objectstack/service-knowledge": 34.06, + "@objectstack/service-mailbox": 67.92, + "@objectstack/service-messaging": 120.65, + "@objectstack/service-package": 32.97, + "@objectstack/service-print": 29.92, + "@objectstack/service-queue": 33.57, + "@objectstack/service-realtime": 8.09, + "@objectstack/service-settings": 147.44, + "@objectstack/service-sms": 8.95, + "@objectstack/service-storage": 150.72, + "@objectstack/spec": 1168.98, + "@objectstack/trigger-api": 10.92, + "@objectstack/trigger-record-change": 56.43, + "@objectstack/trigger-schedule": 33.51, + "@objectstack/types": 19.54, + "@objectstack/verify": 376.32, + "@objectstack/vitest-filter-preflight": 13.41, + "create-objectstack": 13.77 }, "skippedAsCached": [ "@objectstack/cli", + "@objectstack/client", + "@objectstack/client-react", "@objectstack/cloud-connection", "@objectstack/connector-mcp", + "@objectstack/connector-openapi", "@objectstack/connector-rest", + "@objectstack/connector-slack", "@objectstack/core", "@objectstack/downstream-contract", + "@objectstack/driver-memory", + "@objectstack/driver-mongodb", + "@objectstack/driver-sql", "@objectstack/driver-sqlite-wasm", "@objectstack/driver-turso", + "@objectstack/embedder-openai", "@objectstack/example-crm", "@objectstack/example-embed-objectql", + "@objectstack/example-showcase", + "@objectstack/example-todo", "@objectstack/formula", + "@objectstack/hono", "@objectstack/http-conformance", + "@objectstack/knowledge-memory", "@objectstack/knowledge-ragflow", "@objectstack/lint", "@objectstack/mcp", "@objectstack/metadata", - "@objectstack/metadata-core", "@objectstack/metadata-fs", "@objectstack/metadata-protocol", "@objectstack/objectql", @@ -195,6 +294,7 @@ "@objectstack/platform-objects", "@objectstack/plugin-approvals", "@objectstack/plugin-audit", + "@objectstack/plugin-auth", "@objectstack/plugin-dev", "@objectstack/plugin-email", "@objectstack/plugin-hono-server", @@ -204,31 +304,45 @@ "@objectstack/plugin-webhooks", "@objectstack/rest", "@objectstack/runtime", + "@objectstack/sdui-parser", "@objectstack/service-analytics", "@objectstack/service-automation", "@objectstack/service-cache", - "@objectstack/service-cluster-redis", + "@objectstack/service-datasource", + "@objectstack/service-i18n", "@objectstack/service-job", "@objectstack/service-knowledge", "@objectstack/service-mailbox", "@objectstack/service-messaging", "@objectstack/service-package", + "@objectstack/service-print", + "@objectstack/service-queue", + "@objectstack/service-realtime", "@objectstack/service-settings", - "@objectstack/service-sms", "@objectstack/service-storage", "@objectstack/spec", "@objectstack/trigger-api", "@objectstack/trigger-record-change", "@objectstack/trigger-schedule", - "@objectstack/types", - "@objectstack/vitest-filter-preflight", - "create-objectstack" + "@objectstack/verify", + "@objectstack/vitest-filter-preflight" ], "skippedIncompleteSlices": [ - "@objectstack/cli in run 39943147947 (missing 2/3, 3/3)" + "@objectstack/cli in run 40209651657 (missing 1/3, 2/3)", + "@objectstack/cli in run 40214410982 (missing 1/3, 2/3)", + "@objectstack/cli in run 40266979145 (missing 2/3, 3/3)" ], "carriedOver": [], - "provisional": [], + "provisional": [ + "@objectstack/metadata-protocol", + "@objectstack/plugin-audit", + "@objectstack/plugin-sharing", + "@objectstack/rest", + "@objectstack/runtime", + "@objectstack/service-analytics", + "@objectstack/service-automation", + "@objectstack/verify" + ], "ceilings": { "@objectstack/cli": 2868.12, "@objectstack/client": 179.74, @@ -310,114 +424,138 @@ "density": { "runs": [ { - "run": "39943147947", - "executed": 49 + "run": "40272142430", + "executed": 20 }, { - "run": "39936055900", - "executed": 54 + "run": "40266979145", + "executed": 59 }, { - "run": "39928834751", - "executed": 43 + "run": "40262173089", + "executed": 58 }, { - "run": "39921744055", - "executed": 75 + "run": "40257470166", + "executed": 58 + }, + { + "run": "40242835329", + "executed": 32 + }, + { + "run": "40238189261", + "executed": 33 + }, + { + "run": "40233481335", + "executed": 29 + }, + { + "run": "40228747755", + "executed": 20 + }, + { + "run": "40223991179", + "executed": 20 + }, + { + "run": "40219252911", + "executed": 20 }, { - "run": "39915751898", - "executed": 69 + "run": "40214410982", + "executed": 40 }, { - "run": "39909025131", - "executed": 70 + "run": "40209651657", + "executed": 40 }, { - "run": "39903431405", + "run": "40204927516", "executed": 75 }, { - "run": "39898100438", - "executed": 72 + "run": "40200279306", + "executed": 73 } ], "shares": { - "@objectstack/cli": 0.2164, - "@objectstack/client": 0.01174, - "@objectstack/client-react": 0.0009241, - "@objectstack/cloud-connection": 0.01921, - "@objectstack/connector-imap": 0.0002767, - "@objectstack/connector-mcp": 0.002915, - "@objectstack/connector-openapi": 0.0026, - "@objectstack/connector-rest": 0.002878, - "@objectstack/connector-slack": 0.002672, - "@objectstack/core": 0.01031, - "@objectstack/downstream-contract": 0.001177, - "@objectstack/driver-memory": 0.01114, - "@objectstack/driver-mongodb": 0.007783, - "@objectstack/driver-sql": 0.03059, - "@objectstack/driver-sqlite-wasm": 0.007015, - "@objectstack/driver-turso": 0.01846, - "@objectstack/embedder-openai": 0.0004014, - "@objectstack/example-crm": 0.003057, - "@objectstack/example-embed-objectql": 0.002133, - "@objectstack/example-showcase": 0.01, - "@objectstack/example-todo": 0.004714, - "@objectstack/formula": 0.003693, - "@objectstack/hono": 0.003341, - "@objectstack/http-conformance": 0.0101, - "@objectstack/knowledge-memory": 0.0003478, - "@objectstack/knowledge-ragflow": 0.000354, - "@objectstack/lint": 0.01451, - "@objectstack/mcp": 0.008144, - "@objectstack/metadata": 0.01135, - "@objectstack/metadata-core": 0.001921, - "@objectstack/metadata-fs": 0.003133, - "@objectstack/metadata-protocol": 0.05059, - "@objectstack/objectql": 0.07109, - "@objectstack/observability": 0.0002716, - "@objectstack/organizations": 0.00686, - "@objectstack/platform-objects": 0.009257, - "@objectstack/plugin-approvals": 0.02386, - "@objectstack/plugin-audit": 0.01921, - "@objectstack/plugin-auth": 0.03314, - "@objectstack/plugin-dev": 0.00361, - "@objectstack/plugin-email": 0.009403, - "@objectstack/plugin-hono-server": 0.005618, - "@objectstack/plugin-pinyin-search": 0.002891, - "@objectstack/plugin-security": 0.03053, - "@objectstack/plugin-sharing": 0.01499, - "@objectstack/plugin-webhooks": 0.006986, - "@objectstack/rest": 0.06441, - "@objectstack/runtime": 0.06859, - "@objectstack/sdui-parser": 0.0003479, - "@objectstack/service-analytics": 0.03143, - "@objectstack/service-automation": 0.04294, - "@objectstack/service-cache": 0.000132, - "@objectstack/service-cluster": 0.001845, - "@objectstack/service-cluster-redis": 0.00155, - "@objectstack/service-datasource": 0.009756, - "@objectstack/service-i18n": 0.001535, - "@objectstack/service-job": 0.002369, - "@objectstack/service-knowledge": 0.002017, - "@objectstack/service-mailbox": 0.004452, - "@objectstack/service-messaging": 0.01318, - "@objectstack/service-package": 0.004403, - "@objectstack/service-print": 0.002653, - "@objectstack/service-queue": 0.003507, - "@objectstack/service-realtime": 0.00076, - "@objectstack/service-settings": 0.01091, - "@objectstack/service-sms": 0.001988, - "@objectstack/service-storage": 0.01645, - "@objectstack/spec": 0.09904, - "@objectstack/trigger-api": 0.001217, - "@objectstack/trigger-record-change": 0.006333, - "@objectstack/trigger-schedule": 0.003499, - "@objectstack/types": 0.001908, - "@objectstack/verify": 0.01721, - "@objectstack/vitest-filter-preflight": 0.00254, - "create-objectstack": 0.001995 + "@objectstack/cli": 0.2175, + "@objectstack/client": 0.01878, + "@objectstack/client-react": 0.002868, + "@objectstack/cloud-connection": 0.03284, + "@objectstack/connector-imap": 0.001097, + "@objectstack/connector-mcp": 0.007916, + "@objectstack/connector-openapi": 0.004374, + "@objectstack/connector-rest": 0.006797, + "@objectstack/connector-slack": 0.003776, + "@objectstack/core": 0.017, + "@objectstack/downstream-contract": 0.003234, + "@objectstack/driver-memory": 0.01712, + "@objectstack/driver-mongodb": 0.01244, + "@objectstack/driver-sql": 0.02573, + "@objectstack/driver-sqlite-wasm": 0.0106, + "@objectstack/driver-turso": 0.02147, + "@objectstack/embedder-openai": 0.001983, + "@objectstack/example-crm": 0.004883, + "@objectstack/example-embed-objectql": 0.003669, + "@objectstack/example-showcase": 0.01117, + "@objectstack/example-todo": 0.004618, + "@objectstack/formula": 0.01122, + "@objectstack/hono": 0.004841, + "@objectstack/http-conformance": 0.01206, + "@objectstack/knowledge-memory": 0.000795, + "@objectstack/knowledge-ragflow": 0.001635, + "@objectstack/lint": 0.0241, + "@objectstack/mcp": 0.011, + "@objectstack/metadata": 0.03279, + "@objectstack/metadata-core": 0.00486, + "@objectstack/metadata-fs": 0.003597, + "@objectstack/metadata-protocol": 0.05121, + "@objectstack/objectql": 0.1187, + "@objectstack/observability": 0.001056, + "@objectstack/organizations": 0.01782, + "@objectstack/platform-objects": 0.01368, + "@objectstack/plugin-approvals": 0.01971, + "@objectstack/plugin-audit": 0.01955, + "@objectstack/plugin-auth": 0.04246, + "@objectstack/plugin-dev": 0.008368, + "@objectstack/plugin-email": 0.02333, + "@objectstack/plugin-hono-server": 0.01322, + "@objectstack/plugin-pinyin-search": 0.009586, + "@objectstack/plugin-security": 0.04182, + "@objectstack/plugin-sharing": 0.01147, + "@objectstack/plugin-webhooks": 0.007615, + "@objectstack/rest": 0.04352, + "@objectstack/runtime": 0.06059, + "@objectstack/sdui-parser": 0.001406, + "@objectstack/service-analytics": 0.03101, + "@objectstack/service-automation": 0.03996, + "@objectstack/service-cache": 0.0006902, + "@objectstack/service-cluster": 0.003502, + "@objectstack/service-cluster-redis": 0.003888, + "@objectstack/service-datasource": 0.01368, + "@objectstack/service-i18n": 0.002411, + "@objectstack/service-job": 0.003756, + "@objectstack/service-knowledge": 0.005797, + "@objectstack/service-mailbox": 0.01569, + "@objectstack/service-messaging": 0.01734, + "@objectstack/service-package": 0.005475, + "@objectstack/service-print": 0.006634, + "@objectstack/service-queue": 0.006008, + "@objectstack/service-realtime": 0.002314, + "@objectstack/service-settings": 0.04004, + "@objectstack/service-sms": 0.003692, + "@objectstack/service-storage": 0.03974, + "@objectstack/spec": 0.2647, + "@objectstack/trigger-api": 0.00402, + "@objectstack/trigger-record-change": 0.009983, + "@objectstack/trigger-schedule": 0.007522, + "@objectstack/types": 0.005565, + "@objectstack/verify": 0.02873, + "@objectstack/vitest-filter-preflight": 0.005587, + "create-objectstack": 0.005706 } } }