slopbrick 0.18.5 → 0.18.7

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.js CHANGED
@@ -19,7 +19,7 @@ var VERSION;
19
19
  var init_header = __esm({
20
20
  "src/types/_header.ts"() {
21
21
  "use strict";
22
- VERSION = "0.18.5";
22
+ VERSION = "0.18.7";
23
23
  }
24
24
  });
25
25
 
@@ -29747,6 +29747,9 @@ var init_expired_code_example = __esm({
29747
29747
  const issues = [];
29748
29748
  const source = facts.v2?._source;
29749
29749
  if (!source) return issues;
29750
+ const packages = declaredPackages(context.cwd);
29751
+ const packageName = context.packageName;
29752
+ if (packageName) packages.add(packageName);
29750
29753
  const blocks = extractFencedCodeBlocks(source);
29751
29754
  for (const block of blocks) {
29752
29755
  if (!CODE_LANGS.has(block.lang)) continue;
@@ -29754,7 +29757,7 @@ var init_expired_code_example = __esm({
29754
29757
  const imports = extractImports(block.body);
29755
29758
  for (const imp of imports) {
29756
29759
  const pkgName = stripSubpath(imp);
29757
- if (context.packages.has(pkgName)) continue;
29760
+ if (packages.has(pkgName)) continue;
29758
29761
  issues.push({
29759
29762
  ruleId: "docs/expired-code-example",
29760
29763
  category: "docs",
@@ -29809,7 +29812,12 @@ function collectExports(cwd) {
29809
29812
  /\bexport\s+class\s+([A-Za-z_$][\w$]*)/g,
29810
29813
  /\bexport\s+interface\s+([A-Za-z_$][\w$]*)/g,
29811
29814
  /\bexport\s+type\s+([A-Za-z_$][\w$]*)/g,
29812
- /\bexport\s+default\s+(?:function\s+|class\s+)?([A-Za-z_$][\w$]*)/g
29815
+ /\bexport\s+default\s+(?:function\s+|class\s+)?([A-Za-z_$][\w$]*)/g,
29816
+ // v0.18.6: also collect field names from `export interface` and
29817
+ // `export type` declarations. Without this, fields like
29818
+ // `crossFileDrift`, `aiQuality`, `engineeringHygiene` are
29819
+ // flagged as stale even though they're valid type fields.
29820
+ /^\s*(?:readonly\s+)?([A-Za-z_$][\w$]*)\s*[?:]/gm
29813
29821
  ]) {
29814
29822
  let m;
29815
29823
  while ((m = re.exec(source)) !== null) {
@@ -29820,6 +29828,21 @@ function collectExports(cwd) {
29820
29828
  }
29821
29829
  return out;
29822
29830
  }
29831
+ function looksLikeProseLabel(inside) {
29832
+ const trimmed = inside.trim();
29833
+ if (trimmed.length === 0) return false;
29834
+ if (trimmed.startsWith("`") || trimmed.startsWith("/")) return true;
29835
+ if (trimmed.includes("`")) return true;
29836
+ if (/\d+\s+[a-z]/i.test(trimmed)) return true;
29837
+ const parts = trimmed.split(",").map((s) => s.trim());
29838
+ if (parts.length >= 3) {
29839
+ const allNumeric = parts.every((p) => /^\d+\.?\d*$/.test(p));
29840
+ if (!allNumeric) return true;
29841
+ }
29842
+ if (trimmed.length > 40 && !trimmed.includes(",")) return true;
29843
+ if (trimmed.includes("\u2014") || trimmed.includes("\u2013")) return true;
29844
+ return false;
29845
+ }
29823
29846
  var RESERVED, SOURCE_EXTS, SOURCE_ROOTS, CAP, staleFunctionReferenceRule;
29824
29847
  var init_stale_function_reference = __esm({
29825
29848
  "src/rules/docs/stale-function-reference.ts"() {
@@ -29827,6 +29850,7 @@ var init_stale_function_reference = __esm({
29827
29850
  init_rule();
29828
29851
  init_doc_freshness();
29829
29852
  RESERVED = /* @__PURE__ */ new Set([
29853
+ // JS reserved words
29830
29854
  "true",
29831
29855
  "false",
29832
29856
  "null",
@@ -29926,7 +29950,472 @@ var init_stale_function_reference = __esm({
29926
29950
  "next",
29927
29951
  "vue",
29928
29952
  "angular",
29929
- "svelte"
29953
+ "svelte",
29954
+ // Framework / runtime names
29955
+ "html",
29956
+ "astro",
29957
+ "python",
29958
+ "jvm",
29959
+ "kotlin",
29960
+ "swift",
29961
+ "dart",
29962
+ "ruby",
29963
+ "rust",
29964
+ "cpp",
29965
+ "go",
29966
+ "java",
29967
+ "php",
29968
+ "php-html",
29969
+ "csharp",
29970
+ "typescript",
29971
+ "javascript",
29972
+ "jsx",
29973
+ "tsx",
29974
+ "mjs",
29975
+ "cjs",
29976
+ "esnext",
29977
+ "es6",
29978
+ "es2022",
29979
+ "es2023",
29980
+ "esm",
29981
+ "cjs",
29982
+ "umd",
29983
+ "amd",
29984
+ "commonjs",
29985
+ "require",
29986
+ "module",
29987
+ "exports",
29988
+ "define",
29989
+ "global",
29990
+ "window",
29991
+ "document",
29992
+ "process",
29993
+ "console",
29994
+ "buffer",
29995
+ "stream",
29996
+ "fetch",
29997
+ "axios",
29998
+ "express",
29999
+ "fastify",
30000
+ "koa",
30001
+ "hapi",
30002
+ "nextjs",
30003
+ "nuxt",
30004
+ "remix",
30005
+ "gatsby",
30006
+ "sveltekit",
30007
+ "solid",
30008
+ "preact",
30009
+ "qwik",
30010
+ "lit",
30011
+ "stencil",
30012
+ "marko",
30013
+ "alpine",
30014
+ "stimulus",
30015
+ "turbo",
30016
+ "hotwire",
30017
+ // Models / providers
30018
+ "gpt",
30019
+ "claude",
30020
+ "gpt-3",
30021
+ "gpt-3.5",
30022
+ "gpt-4",
30023
+ "gpt-oss",
30024
+ "haiku",
30025
+ "sonnet",
30026
+ "opus",
30027
+ "aider",
30028
+ "tabby",
30029
+ "copilot",
30030
+ "cursor",
30031
+ "windsurf",
30032
+ "devin",
30033
+ "claude-code",
30034
+ // LLM-detection lingo
30035
+ "heuristic",
30036
+ "heuristics",
30037
+ "calibrate",
30038
+ "calibration",
30039
+ "calibrator",
30040
+ "corpus",
30041
+ "baseline",
30042
+ "baselines",
30043
+ "corpus-baselines",
30044
+ "lift",
30045
+ "recall",
30046
+ "precision",
30047
+ "fpRate",
30048
+ "ratio",
30049
+ "verdict",
30050
+ "USEFUL",
30051
+ "NOISY",
30052
+ "INVERTED",
30053
+ "HYGIENE",
30054
+ "DORMANT",
30055
+ "OK",
30056
+ "aiSpecific",
30057
+ "defaultOff",
30058
+ // Common slop-audit verbs/nouns
30059
+ "commit",
30060
+ "push",
30061
+ "reset",
30062
+ "rebase",
30063
+ "merge",
30064
+ "cherry-pick",
30065
+ "revert",
30066
+ "scan",
30067
+ "parse",
30068
+ "build",
30069
+ "test",
30070
+ "lint",
30071
+ "format",
30072
+ "check",
30073
+ "audit",
30074
+ "fix",
30075
+ "patch",
30076
+ "diff",
30077
+ "pr",
30078
+ "ci",
30079
+ "cd",
30080
+ "gh",
30081
+ "npm",
30082
+ "npx",
30083
+ "pnpm",
30084
+ "yaml",
30085
+ "json",
30086
+ "toml",
30087
+ "csv",
30088
+ "md",
30089
+ "mdx",
30090
+ "sh",
30091
+ "bash",
30092
+ "zsh",
30093
+ "fish",
30094
+ "ascii",
30095
+ "utf8",
30096
+ "utf-8",
30097
+ "base64",
30098
+ "hex",
30099
+ "binary",
30100
+ "text",
30101
+ // Common design / ui terms
30102
+ "flex",
30103
+ "grid",
30104
+ "auto",
30105
+ "min",
30106
+ "max",
30107
+ "fill",
30108
+ "stretch",
30109
+ "wrap",
30110
+ "nowrap",
30111
+ "inline",
30112
+ "block",
30113
+ "hidden",
30114
+ "visible",
30115
+ "static",
30116
+ "fixed",
30117
+ "absolute",
30118
+ "relative",
30119
+ "sticky",
30120
+ "pointer",
30121
+ "cursor",
30122
+ "focus",
30123
+ "hover",
30124
+ "active",
30125
+ "disabled",
30126
+ "readonly",
30127
+ "primary",
30128
+ "secondary",
30129
+ "tertiary",
30130
+ "success",
30131
+ "warning",
30132
+ "danger",
30133
+ "info",
30134
+ "muted",
30135
+ "sm",
30136
+ "md",
30137
+ "lg",
30138
+ "xl",
30139
+ "xxl",
30140
+ "xs",
30141
+ "2xl",
30142
+ "3xl",
30143
+ "4xl",
30144
+ // Math / types
30145
+ "array",
30146
+ "map",
30147
+ "set",
30148
+ "weakmap",
30149
+ "weakset",
30150
+ "object",
30151
+ "string",
30152
+ "number",
30153
+ "boolean",
30154
+ "bigint",
30155
+ "symbol",
30156
+ "null",
30157
+ "undefined",
30158
+ "any",
30159
+ "unknown",
30160
+ "never",
30161
+ "void",
30162
+ "readonly",
30163
+ "private",
30164
+ "public",
30165
+ "protected",
30166
+ "static",
30167
+ "abstract",
30168
+ "async",
30169
+ "generator",
30170
+ "iterator",
30171
+ "iterable",
30172
+ "promise",
30173
+ "observable",
30174
+ // Auth / domain
30175
+ "admin",
30176
+ "user",
30177
+ "guest",
30178
+ "anonymous",
30179
+ "authenticated",
30180
+ "unauthenticated",
30181
+ "jwt",
30182
+ "oauth",
30183
+ "oidc",
30184
+ "saml",
30185
+ "csrf",
30186
+ "xss",
30187
+ "sql",
30188
+ "nosql",
30189
+ "orm",
30190
+ "prisma",
30191
+ "drizzle",
30192
+ "sequelize",
30193
+ "mongoose",
30194
+ "redis",
30195
+ "postgres",
30196
+ "mysql",
30197
+ "sqlite",
30198
+ "kafka",
30199
+ "rabbitmq",
30200
+ "graphql",
30201
+ "rest",
30202
+ "grpc",
30203
+ "websocket",
30204
+ // slop-audit specific
30205
+ "slopbrick",
30206
+ "usebrick",
30207
+ "deadcode",
30208
+ "unused",
30209
+ "orphan",
30210
+ "zombie",
30211
+ "blocker",
30212
+ "warning",
30213
+ "info",
30214
+ "error",
30215
+ "verbose",
30216
+ "debug",
30217
+ "silly",
30218
+ "p50",
30219
+ "p90",
30220
+ "p95",
30221
+ "p99",
30222
+ "min",
30223
+ "max",
30224
+ "avg",
30225
+ "mean",
30226
+ "median",
30227
+ "ratchet",
30228
+ "tier",
30229
+ "composite",
30230
+ "fitness",
30231
+ "fpr",
30232
+ "tpr",
30233
+ "roc",
30234
+ "should",
30235
+ "could",
30236
+ "would",
30237
+ "might",
30238
+ "must",
30239
+ "shall",
30240
+ "may",
30241
+ "can",
30242
+ "todo",
30243
+ "fixme",
30244
+ "xxx",
30245
+ "hack",
30246
+ "note",
30247
+ "warning",
30248
+ "attention",
30249
+ "h1",
30250
+ "h2",
30251
+ "h3",
30252
+ "h4",
30253
+ "h5",
30254
+ "h6",
30255
+ "strong",
30256
+ "em",
30257
+ "b",
30258
+ "i",
30259
+ "u",
30260
+ "true",
30261
+ "false",
30262
+ "yes",
30263
+ "no",
30264
+ "on",
30265
+ "off",
30266
+ "enable",
30267
+ "disable",
30268
+ "ltr",
30269
+ "rtl",
30270
+ "auto",
30271
+ "start",
30272
+ "end",
30273
+ "center",
30274
+ "baseline",
30275
+ "stretch",
30276
+ "rounded",
30277
+ "sharp",
30278
+ "outline",
30279
+ "ghost",
30280
+ "link",
30281
+ "filled",
30282
+ "row",
30283
+ "col",
30284
+ "gap",
30285
+ "pad",
30286
+ "margin",
30287
+ "padding",
30288
+ "border",
30289
+ "shadow",
30290
+ "transparent",
30291
+ "currentcolor",
30292
+ "inherit",
30293
+ "initial",
30294
+ "unset",
30295
+ "revert",
30296
+ "hover",
30297
+ "focus",
30298
+ "active",
30299
+ "disabled",
30300
+ "checked",
30301
+ "indeterminate",
30302
+ "open",
30303
+ "close",
30304
+ "expanded",
30305
+ "collapsed",
30306
+ "selected",
30307
+ "pressed",
30308
+ // Web/CSS
30309
+ "div",
30310
+ "span",
30311
+ "p",
30312
+ "a",
30313
+ "img",
30314
+ "ul",
30315
+ "ol",
30316
+ "li",
30317
+ "table",
30318
+ "tr",
30319
+ "td",
30320
+ "th",
30321
+ "thead",
30322
+ "tbody",
30323
+ "tfoot",
30324
+ "caption",
30325
+ "figure",
30326
+ "figcaption",
30327
+ "main",
30328
+ "section",
30329
+ "article",
30330
+ "aside",
30331
+ "header",
30332
+ "footer",
30333
+ "nav",
30334
+ "form",
30335
+ "input",
30336
+ "button",
30337
+ "select",
30338
+ "option",
30339
+ "textarea",
30340
+ "label",
30341
+ "fieldset",
30342
+ "legend",
30343
+ "details",
30344
+ "summary",
30345
+ "dialog",
30346
+ "menu",
30347
+ "menuitem",
30348
+ "template",
30349
+ "slot",
30350
+ "picture",
30351
+ "source",
30352
+ "track",
30353
+ "video",
30354
+ "audio",
30355
+ "canvas",
30356
+ "svg",
30357
+ "iframe",
30358
+ "embed",
30359
+ "object",
30360
+ "portal",
30361
+ // Common business terms
30362
+ "api",
30363
+ "cli",
30364
+ "ui",
30365
+ "ux",
30366
+ "sdk",
30367
+ "ide",
30368
+ "cli",
30369
+ "docs",
30370
+ "doc",
30371
+ "blog",
30372
+ "post",
30373
+ "page",
30374
+ "view",
30375
+ "tab",
30376
+ "panel",
30377
+ "card",
30378
+ "list",
30379
+ "grid",
30380
+ "form",
30381
+ "modal",
30382
+ "menu",
30383
+ "button",
30384
+ "icon",
30385
+ "avatar",
30386
+ "badge",
30387
+ "chip",
30388
+ "tooltip",
30389
+ "popover",
30390
+ "dropdown",
30391
+ "banner",
30392
+ "alert",
30393
+ "toast",
30394
+ "notification",
30395
+ "drawer",
30396
+ "sidebar",
30397
+ "navbar",
30398
+ "header",
30399
+ "footer",
30400
+ "hero",
30401
+ "cta",
30402
+ "cta-primary",
30403
+ "cta-secondary",
30404
+ "pricing",
30405
+ "price",
30406
+ "cost",
30407
+ "rate",
30408
+ "percent",
30409
+ "pct",
30410
+ "count",
30411
+ "total",
30412
+ "small",
30413
+ "medium",
30414
+ "large",
30415
+ "xl",
30416
+ "xxl",
30417
+ "tiny",
30418
+ "huge"
29930
30419
  ]);
29931
30420
  SOURCE_EXTS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
29932
30421
  SOURCE_ROOTS = ["src", "lib", "app", "components"];
@@ -29950,8 +30439,39 @@ var init_stale_function_reference = __esm({
29950
30439
  if (text.length < 3) continue;
29951
30440
  if (RESERVED.has(text.toLowerCase())) continue;
29952
30441
  if (context.exports.has(text)) continue;
29953
- const end = Math.min(source.length, span.index + text.length + 50);
29954
- if (!/\(/.test(source.slice(span.index, end))) continue;
30442
+ const lineEnd = source.indexOf("\n", span.index);
30443
+ const restOfLine = source.slice(
30444
+ span.index,
30445
+ lineEnd === -1 ? source.length : lineEnd
30446
+ );
30447
+ const closeTick = restOfLine.indexOf("`", 1);
30448
+ if (closeTick === -1) continue;
30449
+ const afterTick = restOfLine.slice(closeTick + 1);
30450
+ const directCall = /^\s*\(/.test(afterTick);
30451
+ let identifierRepeats = false;
30452
+ if (!directCall) {
30453
+ const afterSpan = restOfLine.slice(closeTick + 1);
30454
+ const needle = text + "(";
30455
+ identifierRepeats = afterSpan.indexOf(needle) !== -1;
30456
+ }
30457
+ if (!directCall && !identifierRepeats) continue;
30458
+ const beforeTickIdx = span.index - 1;
30459
+ const beforeChar = beforeTickIdx >= 0 ? source[beforeTickIdx] : "";
30460
+ if (beforeChar === "." || beforeChar === "|") continue;
30461
+ const parenStart = restOfLine.indexOf("(", closeTick);
30462
+ const parenEnd = restOfLine.indexOf(")", parenStart);
30463
+ if (parenStart !== -1 && parenEnd !== -1) {
30464
+ const inside = restOfLine.slice(parenStart + 1, parenEnd);
30465
+ const trimmed = inside.trim();
30466
+ if (looksLikeProseLabel(inside)) continue;
30467
+ const looksLikeTypeAnnotation = !inside.includes(":") && (/\b(string|number|boolean|null|undefined|object|array|required|optional|categorical|direct|n\/a|\bmapped\b|0[\-–][0-9]+|v[0-9]|higher is better|lower is better|added in|deprecated|pr-[0-9])\b/i.test(
30468
+ inside
30469
+ ) || // Short single-word label (≤ 24 chars, no `,`,
30470
+ // doesn't look like a function arg). Real function
30471
+ // calls are usually longer or contain commas.
30472
+ trimmed.length > 0 && trimmed.length <= 24 && !trimmed.includes(",") && /[a-zA-Z]/.test(trimmed));
30473
+ if (looksLikeTypeAnnotation) continue;
30474
+ }
29955
30475
  issues.push({
29956
30476
  ruleId: "docs/stale-function-reference",
29957
30477
  category: "docs",
@@ -30031,7 +30551,33 @@ var init_stale_package_reference = __esm({
30031
30551
  "jsx",
30032
30552
  "ok",
30033
30553
  "no",
30034
- "yes"
30554
+ "yes",
30555
+ // v0.18.6: common English adjectives / adverbs that frequently
30556
+ // appear in backticked prose but are not package names.
30557
+ "aspirational",
30558
+ "concrete",
30559
+ "abstract",
30560
+ "inline",
30561
+ "exposed",
30562
+ "deprecated",
30563
+ "experimental",
30564
+ "stable",
30565
+ "beta",
30566
+ "alpha",
30567
+ "wip",
30568
+ "draft",
30569
+ "final",
30570
+ "shim",
30571
+ "polyfill",
30572
+ "stub",
30573
+ "mock",
30574
+ "fake",
30575
+ "real",
30576
+ "false",
30577
+ "true",
30578
+ "optional",
30579
+ "required",
30580
+ "default"
30035
30581
  ]);
30036
30582
  stalePackageReferenceRule = createRule({
30037
30583
  id: "docs/stale-package-reference",
@@ -30256,7 +30802,15 @@ async function buildDocFreshness(cwd, config, options = {}) {
30256
30802
  continue;
30257
30803
  }
30258
30804
  const relPath = relative2(cwd, abs);
30259
- const context = { config, filePath: relPath, cwd };
30805
+ let packageName;
30806
+ try {
30807
+ const pkg = JSON.parse(
30808
+ readFileSync8(join7(cwd, "package.json"), "utf-8")
30809
+ );
30810
+ packageName = pkg.name;
30811
+ } catch {
30812
+ }
30813
+ const context = { config, filePath: relPath, cwd, packageName };
30260
30814
  const facts = { filePath: relPath, v2: { _source: source } };
30261
30815
  const ruleConfigs = [
30262
30816
  { rule: stalePackageReferenceRule, ruleId: "docs/stale-package-reference" },
@@ -30369,7 +30923,9 @@ var init_broken_link = __esm({
30369
30923
  if (target.startsWith("#")) continue;
30370
30924
  if (target.startsWith("//")) continue;
30371
30925
  if (target.startsWith("/")) continue;
30372
- const resolved = join8(docDir, target);
30926
+ const filePart = target.split("#")[0] ?? target;
30927
+ if (filePart === "") continue;
30928
+ const resolved = join8(docDir, filePart);
30373
30929
  if (existsSync7(resolved)) continue;
30374
30930
  issues.push({
30375
30931
  ruleId: "docs/broken-link",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slopbrick",
3
- "version": "0.18.5",
3
+ "version": "0.18.7",
4
4
  "description": "Discovered, modeled, and governed repository structure. SlopBrick scans source code, classifies it against 95 rules in 15 categories, computes 4 scores (aiQuality, engineeringHygiene, security, repositoryHealth), and persists the structure for AI agents and CI.",
5
5
  "type": "module",
6
6
  "bin": {