@hublo/sentinel 1.5.0-alpha.24 → 1.5.0-alpha.26

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.
@@ -15,7 +15,7 @@ import {
15
15
  palette,
16
16
  registerAdapters,
17
17
  resolve
18
- } from "../chunk-VQZCC5QQ.js";
18
+ } from "../chunk-WDZRBHMH.js";
19
19
  import {
20
20
  resolveContext
21
21
  } from "../chunk-ZMVI65FF.js";
@@ -5488,8 +5488,8 @@ var metricsHelp = {
5488
5488
  },
5489
5489
  deadLinesPercent: {
5490
5490
  label: "Unreachable lines",
5491
- what: "The share of scanned lines the reachability walk never reached from an entry point.",
5492
- read: "Higher is worse, and only once the entry-point count above says the question was decidable. Read it next to the four counts below rather than alone: one number covering files, exports, symbols and imports hides four different kinds of work.",
5491
+ what: "The share of scanned lines the reachability walk never reached from an entry point, with the share of FILES those lines sit in beside it.",
5492
+ read: "\u26D4 Read the two denominators together or the figure misleads, and that is measured rather than feared. On `apps/nest/microservices/agency` the line share is 60.21%, which reads as a rotten module or a broken tool; neither is true. 490 of its 504 files are reachable, and ONE unreachable file, a seed data table, holds 52 210 lines, 59.3% of the module by itself. A large line share over a small file share means a generated or seed file, not code anyone writes. Higher is worse, and only once the entry-point count above says the question was decidable. Read it next to the four counts below rather than alone: one number covering files, exports, symbols and imports hides four different kinds of work.",
5493
5493
  caveat: "Unreachable here means unreachable WITHIN this module, and that is a measured limitation rather than a theoretical one. A library is consumed from outside the scan, so its files look unreachable: on a sample of 12 files reported dead, 9 of `libs/front/components` and 7 of `libs/nest/auth` are cited elsewhere in the repository, one of them in 356 files. Test, fixture and story files are also outside the reachability graph, verified on a fixture, so a file reached only by a story is reported unreachable; it is true of the product and false of the repository, and `libs/front/components` has one such file of 915 lines.",
5494
5494
  source: "jscpd's dead-code engine, `deadLines` over `totalLines`. The library figures were measured per module with the workspace's own path aliases, and the story case was isolated on a four-file fixture where the only importer was a `.stories.tsx`."
5495
5495
  },
@@ -6009,6 +6009,7 @@ function renderMarkdown(report) {
6009
6009
  const family = familyOf(finding.metric);
6010
6010
  if (family !== void 0) places.set(family, (places.get(family) ?? 0) + 1);
6011
6011
  }
6012
+ const version = report.settings.find((setting) => setting.key === "sentinel")?.value;
6012
6013
  const present = new Set(report.rows.map((row) => row.metric));
6013
6014
  const rows = FAMILIES.filter(
6014
6015
  (family) => family.metrics.some((metric) => present.has(metric)) || places.has(family.label)
@@ -6016,7 +6017,7 @@ function renderMarkdown(report) {
6016
6017
  const row = report.rows.find((candidate) => candidate.metric === family.headline);
6017
6018
  const marker = row?.status === void 0 ? "" : ` (${row.status})`;
6018
6019
  const shown = row?.unit.split(";")[0] ?? "";
6019
- const unit = shown === "" ? "" : `${shown === "%" ? "" : " "}${shown}`;
6020
+ const unit = shown === "" ? "" : `${shown.startsWith("%") ? "" : " "}${shown}`;
6020
6021
  const value = row === void 0 ? "--" : `${figure(row)}${unit}${marker}`;
6021
6022
  const label = helpFor(family.headline)?.label ?? family.label;
6022
6023
  return `| ${label} | ${value} | ${places.get(family.label) ?? 0} |`;
@@ -6037,6 +6038,11 @@ ${report.notes.map((note) => `- ${note.split(". ")[0] ?? note}`).join("\n")}
6037
6038
  "> `(ok)` or `(exceed)` is where a figure sits against a PUBLISHED reference; a figure with no",
6038
6039
  "> marker has none, which is a decision and not a gap. A file breaching several rules counts",
6039
6040
  "> once per rule. The code behind every place is in the `static-analysis.html` artifact.",
6041
+ // ⭐ The version that produced these numbers, because the thresholds a module cannot override
6042
+ // live in the tool: nine gauge limits, the complexity bands, the bundle budgets. Two recaps
6043
+ // from two versions are not comparable, and without this nothing on the comment would say so.
6044
+ // Read from the settings the report already carries rather than from the package a second time.
6045
+ ...version === void 0 ? [] : [`> Measured by sentinel ${version}.`],
6040
6046
  ""
6041
6047
  ].join("\n");
6042
6048
  }
@@ -7379,6 +7385,19 @@ function measuredWith(config) {
7379
7385
  const moved = (key) => config.moved.some((path2) => path2 === key || path2.startsWith(`${key}.`));
7380
7386
  const row = (key, value) => ({ key, value, moved: moved(key) });
7381
7387
  return [
7388
+ /**
7389
+ * ⭐ The tool's own version, first, and it is the same argument this list already makes about
7390
+ * every other line: "6.81% found with `minTokens` at 50 and 6.81% found with it at 100 are not
7391
+ * the same measurement". The version is the stronger case, because the numbers a module cannot
7392
+ * override live HERE: the nine gauge thresholds, the complexity bands, the bundle budgets, and
7393
+ * what each figure's unit means. `max-nested-callbacks` sat at 10 and now sits at 3;
7394
+ * `complexityMax` carried a unit and no longer does. A report that does not name the version
7395
+ * that produced it cannot be held against a report from last month, and nothing on the page
7396
+ * would say why the two disagree.
7397
+ *
7398
+ * Never `moved`: it is not a setting a module can turn, which is exactly why it has to be said.
7399
+ */
7400
+ { key: "sentinel", value: readOwnPackage().version, moved: false },
7382
7401
  row("duplication.minTokens", String(config.duplication.minTokens)),
7383
7402
  row("duplication.minLines", String(config.duplication.minLines)),
7384
7403
  row("duplication.kinds", config.duplication.kinds.join(", ")),
@@ -7755,7 +7774,25 @@ function assembleReport(ctx, config, product, tests, dead, complexity, graph, co
7755
7774
  value: stats.entryPoints ?? 0,
7756
7775
  unit: `of ${stats.files ?? 0} files`
7757
7776
  },
7758
- { metric: "deadLinesPercent", value: share(stats), unit: "%" },
7777
+ /**
7778
+ * ⛔ The share of LINES, with the share of FILES beside it, because one without the other
7779
+ * misleads and this was measured rather than imagined.
7780
+ *
7781
+ * On `apps/nest/microservices/agency` the line share reads **60.21%**, which in a
7782
+ * pull-request comment says the module is rotten or the tool is broken. Neither is true:
7783
+ * 490 of its 504 files are reachable, and a SINGLE unreachable file,
7784
+ * `app/database/seed/data/legacy-agencies.ts`, holds **52 210 lines**, 59.3% of the module on
7785
+ * its own. Twelve files carry 53 233 of the 53 242 dead lines.
7786
+ *
7787
+ * With both denominators the sentence reads correctly at a glance: 60% of the lines sit in
7788
+ * 2% of the files, so the reader looks for a big generated or seed file instead of concluding
7789
+ * anything about the code they write. Nothing is computed that the pass did not hand over.
7790
+ */
7791
+ {
7792
+ metric: "deadLinesPercent",
7793
+ value: share(stats),
7794
+ unit: `% of lines, in ${(stats.files ?? 0) - (stats.reachableFiles ?? 0)} of ${stats.files ?? 0} files`
7795
+ },
7759
7796
  // ⛔ Minus the files the TOOL itself labels `used-only-by-tests`. They were counted as
7760
7797
  // unreachable while the tool knew better: measured on `libs/nest/auth`, 5 of the 20. A file a
7761
7798
  // spec reaches is not unreachable, and leaving it in the headline count meant the figure
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  registerAdapters,
7
7
  resolve,
8
8
  setDefaultRunner
9
- } from "./chunk-VQZCC5QQ.js";
9
+ } from "./chunk-WDZRBHMH.js";
10
10
  import {
11
11
  BaseAdapter
12
12
  } from "./chunk-ZMVI65FF.js";
@@ -214,12 +214,12 @@ A report nobody opens is a report that changes nothing, and the published cases
214
214
  both of them put the figures where the review already happens. So this release does not stop at a
215
215
  page on disk.
216
216
 
217
- | | |
218
- | --------------- | ------------------------------------------------------------------------------------------------------------------- |
219
- | what is posted | a recap of the figures for the fronts the pull request touched, with each band |
220
- | when | every run, not only on a breach: a recap that appears only when something is wrong is a recap nobody learns to read |
221
- | blocking | **no**, and that is a choice for now rather than an end state |
222
- | on a second run | the same comment is updated, never a second one |
217
+ | | |
218
+ | --------------- | ---------------------------------------------------------------------------------------------------------------------- |
219
+ | what is posted | one section per module the pull request touched: six rows, one per family, the headline figure and the places it holds |
220
+ | when | every run, not only on a breach: a recap that appears only when something is wrong is a recap nobody learns to read |
221
+ | blocking | **no**, and that is a choice for now rather than an end state |
222
+ | on a second run | the same comment is updated, never a second one |
223
223
 
224
224
  ⛔ The division of labour matters, because getting it wrong couples this role to one CI provider.
225
225
  **sentinel renders the content, the repository's workflow posts it.** The content is markdown
@@ -227,6 +227,33 @@ produced from the same figures the other three shapes carry, which makes it test
227
227
  identical to what the console printed. Who holds the token, which event triggers it and how a
228
228
  comment is found again are the repository's business, not this role's.
229
229
 
230
+ ### 8.1 What it is, as built
231
+
232
+ ⚠️ It covers the **whole role**, not the bundle alone, and that is a correction to the line above
233
+ that said "the fronts the pull request touched". A pull request touches libraries and services too,
234
+ and a recap that stayed silent on them would teach a reader that this role only speaks about fronts.
235
+ A module with no build gets five rows and a line saying why the sixth is absent.
236
+
237
+ Three decisions worth stating, because each one was a fork:
238
+
239
+ - **The headline per family is declared, not positional.** Three of the six would be wrong taken as
240
+ "the first metric listed": `importEdges` leads structure and is a size rather than a signal, so a
241
+ big module would look bad for being big, and `entryPoints` leads dead code and is the walk's
242
+ starting condition rather than a result.
243
+ - **The row is named by the metric's own help label**, not the family's name. "Duplication | 0.75%"
244
+ does not say of what; "Duplicated lines" does. One wording, shared with the page.
245
+ - **A marker says where a figure sits against a published reference**, `(ok)` included, and a row
246
+ with no marker has no reference rather than sitting inside one. Those are different facts, and
247
+ six of this role's figures genuinely have none.
248
+
249
+ It reads no source file and lays out no graph: a recap shows no code, so it skips both the 201 file
250
+ reads and the 5-second layout the page pays for.
251
+
252
+ ⛔ And it says on itself that it is **not compared with `main`**. See section 9: the delta needs a
253
+ stored baseline. A figure in a pull-request comment is read as a delta by default, and that reading
254
+ is wrong in the dangerous direction, since a module already at 6.81% looks exactly like one this
255
+ branch pushed there.
256
+
230
257
  ## 9. Deferred, with the reason
231
258
 
232
259
  Recorded in issue #97. Both need something this release does not have, and neither changes a figure
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hublo/sentinel",
3
- "version": "1.5.0-alpha.24",
3
+ "version": "1.5.0-alpha.26",
4
4
  "description": "One CLI that guards code health across Hublo repos: shared lint/typescript/build/test presets, static & dynamic analysis, and architecture checks.",
5
5
  "type": "module",
6
6
  "license": "MIT",