@svelte-vitals/core 0.36.1 → 0.37.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.
package/dist/index.d.ts CHANGED
@@ -956,6 +956,14 @@ interface RuleContext {
956
956
  sourceFiles?: string[];
957
957
  project: Project;
958
958
  config: Config;
959
+ /**
960
+ * Report per-declaration counts of places this rule examined. The engine supplies it and keys the
961
+ * result by rule id; a rule that does not call it gets no entry, which is distinct from an entry of
962
+ * zeros. Absent in contexts a caller builds directly. Silent last-write-wins: calling it more than
963
+ * once keeps only the most recent map, with no merge and no error — call it once, with the complete
964
+ * counts, at the end of `check()`.
965
+ */
966
+ recordExamined?: (counts: Record<string, number>) => void;
959
967
  }
960
968
  interface Rule {
961
969
  id: string;
@@ -995,7 +1003,10 @@ declare function isPenalized(detection: Detection, treatDynamicAs: TreatDynamicA
995
1003
  * Rules are independent, so they run concurrently; results are flattened in
996
1004
  * rule order for stable output.
997
1005
  */
998
- declare function runRules(rules: Rule[], ctx: RuleContext): Promise<Result[]>;
1006
+ declare function runRules(rules: Rule[], ctx: RuleContext): Promise<{
1007
+ results: Result[];
1008
+ examined: Record<string, Record<string, number>>;
1009
+ }>;
999
1010
 
1000
1011
  /**
1001
1012
  * seo/title-presence — every route should resolve a non-empty <title> (design §11).
@@ -1554,15 +1565,22 @@ interface JsonReport {
1554
1565
  * and floors that sum once, so adding this map's already-floored entries and re-dividing can disagree.
1555
1566
  */
1556
1567
  inventories: Record<string, number>;
1568
+ /**
1569
+ * Per-rule, per-declaration counts of places examined. Unlike `rules`, this describes the analysis
1570
+ * rather than the report: `--diff`, `--baseline` and suppressions do not narrow it. Three states: a
1571
+ * rule that reports no counts has no entry; a rule that counts but whose configuration declares
1572
+ * nothing has an empty entry; a declaration that judged nothing has an entry of `0`.
1573
+ */
1574
+ examined?: Record<string, Record<string, number>>;
1557
1575
  }
1558
1576
  /** Build the structured JSON report object (design §7). The shape the `json` reporter emits (issue #24). */
1559
1577
  declare function buildJsonReport(results: Result[], config: Config, meta: {
1560
1578
  version: string;
1561
- }, ruleIds?: readonly string[]): JsonReport;
1579
+ }, ruleIds?: readonly string[], examined?: Record<string, Record<string, number>>): JsonReport;
1562
1580
  /** Render results as the documented JSON report string (design §7). */
1563
1581
  declare function formatJsonReport(results: Result[], config: Config, meta: {
1564
1582
  version: string;
1565
- }, ruleIds?: readonly string[]): string;
1583
+ }, ruleIds?: readonly string[], examined?: Record<string, Record<string, number>>): string;
1566
1584
 
1567
1585
  /** Render failing findings as an agent-actionable Markdown remediation document (issue #18). */
1568
1586
  declare function formatAgentReport(results: Result[], config: Config): string;
package/dist/index.js CHANGED
@@ -2444,8 +2444,11 @@ function isPenalized(detection, treatDynamicAs) {
2444
2444
 
2445
2445
  // src/engine.ts
2446
2446
  async function runRules(rules, ctx) {
2447
- const perRule = await Promise.all(rules.map((rule) => rule.check(ctx)));
2448
- return perRule.flat();
2447
+ const examined = {};
2448
+ const perRule = await Promise.all(
2449
+ rules.map((rule) => rule.check({ ...ctx, recordExamined: (counts) => void (examined[rule.id] = counts) }))
2450
+ );
2451
+ return { results: perRule.flat(), examined };
2449
2452
  }
2450
2453
 
2451
2454
  // src/rules/seo/title-presence.ts
@@ -5479,6 +5482,8 @@ var architectureReservedNamePlacement = {
5479
5482
  }
5480
5483
  }
5481
5484
  const usedAlternatives = /* @__PURE__ */ new Set();
5485
+ const examinedCounts = {};
5486
+ for (const key of globalAlternatives.keys()) examinedCounts[key] = 0;
5482
5487
  const allDirs = [...dirs].sort();
5483
5488
  for (const dir of allDirs) {
5484
5489
  const o = resolveRuleOptions(ID7, OPTIONS6, ctx.config, { route: dir, file: dir }, compiledOverrides);
@@ -5503,6 +5508,17 @@ var architectureReservedNamePlacement = {
5503
5508
  if (isExcluded(dir, ancestorDirs2(dir), excluded)) {
5504
5509
  continue;
5505
5510
  }
5511
+ const judged = /* @__PURE__ */ new Set();
5512
+ const resolvedValues = [
5513
+ ["placements", placements[name]],
5514
+ ["capitalisedUnitPlacements", capUnits[name]],
5515
+ ["anyCaseUnitPlacements", anyUnits[name]]
5516
+ ];
5517
+ for (const [map, value] of resolvedValues) {
5518
+ if (value === void 0) continue;
5519
+ for (const glob of globsOf(value)) judged.add(label(map, name, glob));
5520
+ }
5521
+ for (const key of judged) if (globalAlternatives.has(key)) examinedCounts[key] = (examinedCounts[key] ?? 0) + 1;
5506
5522
  const record = (map, value, qualifies) => {
5507
5523
  if (value === void 0) return false;
5508
5524
  const { matched } = matchKeys(parent, compile(globsOf(value), true));
@@ -5571,6 +5587,7 @@ var architectureReservedNamePlacement = {
5571
5587
  docsUrl: docsUrl11
5572
5588
  });
5573
5589
  }
5590
+ ctx.recordExamined?.(examinedCounts);
5574
5591
  return out;
5575
5592
  }
5576
5593
  };
@@ -6258,7 +6275,7 @@ function ruleEvidence(results, config, ruleIds) {
6258
6275
  }
6259
6276
  return out;
6260
6277
  }
6261
- function buildJsonReport(results, config, meta, ruleIds) {
6278
+ function buildJsonReport(results, config, meta, ruleIds, examined) {
6262
6279
  const { health, categories: byCat, weights } = computeHealth(results, config);
6263
6280
  const summary = summarize(results, config);
6264
6281
  const rules = ruleEvidence(results, config, ruleIds);
@@ -6288,10 +6305,21 @@ function buildJsonReport(results, config, meta, ruleIds) {
6288
6305
  const inventories = Object.fromEntries(
6289
6306
  [...buildInventory(config)].map(([pair, weight]) => [pair, Math.max(weight, INVENTORY_FLOOR)])
6290
6307
  );
6291
- return { version: meta.version, score: health, weights, categories, summary, rules, routes, siteIssues, inventories };
6308
+ return {
6309
+ version: meta.version,
6310
+ score: health,
6311
+ weights,
6312
+ categories,
6313
+ summary,
6314
+ rules,
6315
+ routes,
6316
+ siteIssues,
6317
+ inventories,
6318
+ ...examined && Object.keys(examined).length > 0 ? { examined } : {}
6319
+ };
6292
6320
  }
6293
- function formatJsonReport(results, config, meta, ruleIds) {
6294
- return JSON.stringify(buildJsonReport(results, config, meta, ruleIds), null, 2);
6321
+ function formatJsonReport(results, config, meta, ruleIds, examined) {
6322
+ return JSON.stringify(buildJsonReport(results, config, meta, ruleIds, examined), null, 2);
6295
6323
  }
6296
6324
 
6297
6325
  // src/reporter/agent.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svelte-vitals/core",
3
- "version": "0.36.1",
3
+ "version": "0.37.0",
4
4
  "description": "Shared, runtime-agnostic core for svelte-vitals (types, rule engine, scorer, reporter).",
5
5
  "type": "module",
6
6
  "license": "MIT",