slopbrick 0.17.3 → 0.17.4
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/engine/worker.cjs +16 -9
- package/dist/engine/worker.js +14 -7
- package/dist/index.cjs +86 -56
- package/dist/index.js +80 -50
- package/package.json +1 -1
package/dist/engine/worker.cjs
CHANGED
|
@@ -4084,6 +4084,9 @@ var VERDICTS = [
|
|
|
4084
4084
|
"HYGIENE",
|
|
4085
4085
|
"DORMANT"
|
|
4086
4086
|
];
|
|
4087
|
+
function isDefaultOff(verdict) {
|
|
4088
|
+
return verdict === "NOISY" || verdict === "INVERTED" || verdict === "DORMANT";
|
|
4089
|
+
}
|
|
4087
4090
|
var signalStrengthSchema = external_exports.record(
|
|
4088
4091
|
external_exports.string(),
|
|
4089
4092
|
// ruleId
|
|
@@ -4364,7 +4367,11 @@ var FPR_FLOOR = 1e-6;
|
|
|
4364
4367
|
var RECALL_FLOOR = 1e-6;
|
|
4365
4368
|
var LLR_CAP = 13.8;
|
|
4366
4369
|
var DEFAULT_PRIOR_PREVALENCE = 0.3;
|
|
4367
|
-
var ELIGIBLE_VERDICTS =
|
|
4370
|
+
var ELIGIBLE_VERDICTS = new Set(
|
|
4371
|
+
["USEFUL", "OK", "NOISY", "INVERTED", "HYGIENE", "DORMANT"].filter(
|
|
4372
|
+
(v) => v !== "HYGIENE" && !isDefaultOff(v)
|
|
4373
|
+
)
|
|
4374
|
+
);
|
|
4368
4375
|
function loadSignals(signalData) {
|
|
4369
4376
|
const map = /* @__PURE__ */ new Map();
|
|
4370
4377
|
for (const [ruleId, entry] of Object.entries(signalData)) {
|
|
@@ -34909,7 +34916,7 @@ var mathElementUniformityRule = createRule({
|
|
|
34909
34916
|
if (!anchor) anchor = { line: el.line, column: el.column };
|
|
34910
34917
|
}
|
|
34911
34918
|
}
|
|
34912
|
-
const values = [counts.button, counts.input, counts.select].filter((v) => v > 0);
|
|
34919
|
+
const values = [counts.button, counts.input, counts.select].filter((v) => typeof v === "number" && v > 0);
|
|
34913
34920
|
if (values.length < 2) return issues;
|
|
34914
34921
|
const max = Math.max(...values);
|
|
34915
34922
|
const min = Math.min(...values);
|
|
@@ -34958,7 +34965,7 @@ var mathGridUniformityRule = createRule({
|
|
|
34958
34965
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
34959
34966
|
if (total < 4) return issues;
|
|
34960
34967
|
if (h > 1) return issues;
|
|
34961
|
-
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] : { line: 1, column: 1 };
|
|
34968
|
+
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 } : { line: 1, column: 1 };
|
|
34962
34969
|
issues.push({
|
|
34963
34970
|
ruleId: "layout/math-grid-uniformity",
|
|
34964
34971
|
category: "layout",
|
|
@@ -35841,7 +35848,7 @@ var mathGiniClassUsageRule = createRule({
|
|
|
35841
35848
|
if (g < 0.5) return issues;
|
|
35842
35849
|
const sorted = [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
|
|
35843
35850
|
const topStr = sorted.map(([k, v]) => `${k}\xD7${v}`).join(", ");
|
|
35844
|
-
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] : { line: 1, column: 1 };
|
|
35851
|
+
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 } : { line: 1, column: 1 };
|
|
35845
35852
|
issues.push({
|
|
35846
35853
|
ruleId: "logic/math-gini-class-usage",
|
|
35847
35854
|
category: "logic",
|
|
@@ -37660,7 +37667,7 @@ function looksRealistic(value) {
|
|
|
37660
37667
|
}
|
|
37661
37668
|
|
|
37662
37669
|
// src/rules/test/missing-edge-case.ts
|
|
37663
|
-
var
|
|
37670
|
+
var import_core4 = require("@swc/core");
|
|
37664
37671
|
var import_node_fs11 = require("fs");
|
|
37665
37672
|
var MAX_PER_FILE = 20;
|
|
37666
37673
|
var missingEdgeCaseRule = createRule({
|
|
@@ -37704,7 +37711,7 @@ var missingEdgeCaseRule = createRule({
|
|
|
37704
37711
|
if (!source) return issues;
|
|
37705
37712
|
let ast;
|
|
37706
37713
|
try {
|
|
37707
|
-
ast = (0,
|
|
37714
|
+
ast = (0, import_core4.parseSync)(source, {
|
|
37708
37715
|
syntax: "typescript",
|
|
37709
37716
|
tsx: filePath.endsWith("tsx") || filePath.endsWith("jsx"),
|
|
37710
37717
|
target: "es2022"
|
|
@@ -38821,7 +38828,7 @@ var mathFontEntropyRule = createRule({
|
|
|
38821
38828
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
38822
38829
|
if (total < 6) return issues;
|
|
38823
38830
|
if (h > 1.4) return issues;
|
|
38824
|
-
const anchor = flatClassNames(facts.v2)[0];
|
|
38831
|
+
const anchor = flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 };
|
|
38825
38832
|
issues.push({
|
|
38826
38833
|
ruleId: "visual/math-font-entropy",
|
|
38827
38834
|
category: "visual",
|
|
@@ -38943,7 +38950,7 @@ var mathRoundedEntropyRule = createRule({
|
|
|
38943
38950
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
38944
38951
|
if (total < 6) return issues;
|
|
38945
38952
|
if (h > 1.8) return issues;
|
|
38946
|
-
const anchor = flatClassNames(facts.v2)[0];
|
|
38953
|
+
const anchor = flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 };
|
|
38947
38954
|
issues.push({
|
|
38948
38955
|
ruleId: "visual/math-rounded-entropy",
|
|
38949
38956
|
category: "visual",
|
|
@@ -38982,7 +38989,7 @@ var mathSpacingEntropyRule = createRule({
|
|
|
38982
38989
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
38983
38990
|
if (total < 10) return issues;
|
|
38984
38991
|
if (h > 1.5) return issues;
|
|
38985
|
-
const anchor = flatClassNames(facts.v2)[0];
|
|
38992
|
+
const anchor = flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 };
|
|
38986
38993
|
issues.push({
|
|
38987
38994
|
ruleId: "visual/math-spacing-entropy",
|
|
38988
38995
|
category: "visual",
|
package/dist/engine/worker.js
CHANGED
|
@@ -4065,6 +4065,9 @@ var VERDICTS = [
|
|
|
4065
4065
|
"HYGIENE",
|
|
4066
4066
|
"DORMANT"
|
|
4067
4067
|
];
|
|
4068
|
+
function isDefaultOff(verdict) {
|
|
4069
|
+
return verdict === "NOISY" || verdict === "INVERTED" || verdict === "DORMANT";
|
|
4070
|
+
}
|
|
4068
4071
|
var signalStrengthSchema = external_exports.record(
|
|
4069
4072
|
external_exports.string(),
|
|
4070
4073
|
// ruleId
|
|
@@ -4345,7 +4348,11 @@ var FPR_FLOOR = 1e-6;
|
|
|
4345
4348
|
var RECALL_FLOOR = 1e-6;
|
|
4346
4349
|
var LLR_CAP = 13.8;
|
|
4347
4350
|
var DEFAULT_PRIOR_PREVALENCE = 0.3;
|
|
4348
|
-
var ELIGIBLE_VERDICTS =
|
|
4351
|
+
var ELIGIBLE_VERDICTS = new Set(
|
|
4352
|
+
["USEFUL", "OK", "NOISY", "INVERTED", "HYGIENE", "DORMANT"].filter(
|
|
4353
|
+
(v) => v !== "HYGIENE" && !isDefaultOff(v)
|
|
4354
|
+
)
|
|
4355
|
+
);
|
|
4349
4356
|
function loadSignals(signalData) {
|
|
4350
4357
|
const map = /* @__PURE__ */ new Map();
|
|
4351
4358
|
for (const [ruleId, entry] of Object.entries(signalData)) {
|
|
@@ -34890,7 +34897,7 @@ var mathElementUniformityRule = createRule({
|
|
|
34890
34897
|
if (!anchor) anchor = { line: el.line, column: el.column };
|
|
34891
34898
|
}
|
|
34892
34899
|
}
|
|
34893
|
-
const values = [counts.button, counts.input, counts.select].filter((v) => v > 0);
|
|
34900
|
+
const values = [counts.button, counts.input, counts.select].filter((v) => typeof v === "number" && v > 0);
|
|
34894
34901
|
if (values.length < 2) return issues;
|
|
34895
34902
|
const max = Math.max(...values);
|
|
34896
34903
|
const min = Math.min(...values);
|
|
@@ -34939,7 +34946,7 @@ var mathGridUniformityRule = createRule({
|
|
|
34939
34946
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
34940
34947
|
if (total < 4) return issues;
|
|
34941
34948
|
if (h > 1) return issues;
|
|
34942
|
-
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] : { line: 1, column: 1 };
|
|
34949
|
+
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 } : { line: 1, column: 1 };
|
|
34943
34950
|
issues.push({
|
|
34944
34951
|
ruleId: "layout/math-grid-uniformity",
|
|
34945
34952
|
category: "layout",
|
|
@@ -35822,7 +35829,7 @@ var mathGiniClassUsageRule = createRule({
|
|
|
35822
35829
|
if (g < 0.5) return issues;
|
|
35823
35830
|
const sorted = [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
|
|
35824
35831
|
const topStr = sorted.map(([k, v]) => `${k}\xD7${v}`).join(", ");
|
|
35825
|
-
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] : { line: 1, column: 1 };
|
|
35832
|
+
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 } : { line: 1, column: 1 };
|
|
35826
35833
|
issues.push({
|
|
35827
35834
|
ruleId: "logic/math-gini-class-usage",
|
|
35828
35835
|
category: "logic",
|
|
@@ -38802,7 +38809,7 @@ var mathFontEntropyRule = createRule({
|
|
|
38802
38809
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
38803
38810
|
if (total < 6) return issues;
|
|
38804
38811
|
if (h > 1.4) return issues;
|
|
38805
|
-
const anchor = flatClassNames(facts.v2)[0];
|
|
38812
|
+
const anchor = flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 };
|
|
38806
38813
|
issues.push({
|
|
38807
38814
|
ruleId: "visual/math-font-entropy",
|
|
38808
38815
|
category: "visual",
|
|
@@ -38924,7 +38931,7 @@ var mathRoundedEntropyRule = createRule({
|
|
|
38924
38931
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
38925
38932
|
if (total < 6) return issues;
|
|
38926
38933
|
if (h > 1.8) return issues;
|
|
38927
|
-
const anchor = flatClassNames(facts.v2)[0];
|
|
38934
|
+
const anchor = flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 };
|
|
38928
38935
|
issues.push({
|
|
38929
38936
|
ruleId: "visual/math-rounded-entropy",
|
|
38930
38937
|
category: "visual",
|
|
@@ -38963,7 +38970,7 @@ var mathSpacingEntropyRule = createRule({
|
|
|
38963
38970
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
38964
38971
|
if (total < 10) return issues;
|
|
38965
38972
|
if (h > 1.5) return issues;
|
|
38966
|
-
const anchor = flatClassNames(facts.v2)[0];
|
|
38973
|
+
const anchor = flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 };
|
|
38967
38974
|
issues.push({
|
|
38968
38975
|
ruleId: "visual/math-spacing-entropy",
|
|
38969
38976
|
category: "visual",
|
package/dist/index.cjs
CHANGED
|
@@ -30242,7 +30242,7 @@ var init_math_element_uniformity = __esm({
|
|
|
30242
30242
|
if (!anchor) anchor = { line: el.line, column: el.column };
|
|
30243
30243
|
}
|
|
30244
30244
|
}
|
|
30245
|
-
const values = [counts.button, counts.input, counts.select].filter((v) => v > 0);
|
|
30245
|
+
const values = [counts.button, counts.input, counts.select].filter((v) => typeof v === "number" && v > 0);
|
|
30246
30246
|
if (values.length < 2) return issues;
|
|
30247
30247
|
const max = Math.max(...values);
|
|
30248
30248
|
const min = Math.min(...values);
|
|
@@ -30300,7 +30300,7 @@ var init_math_grid_uniformity = __esm({
|
|
|
30300
30300
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
30301
30301
|
if (total < 4) return issues;
|
|
30302
30302
|
if (h > 1) return issues;
|
|
30303
|
-
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] : { line: 1, column: 1 };
|
|
30303
|
+
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 } : { line: 1, column: 1 };
|
|
30304
30304
|
issues.push({
|
|
30305
30305
|
ruleId: "layout/math-grid-uniformity",
|
|
30306
30306
|
category: "layout",
|
|
@@ -34733,59 +34733,77 @@ __export(dist_exports, {
|
|
|
34733
34733
|
writeCacheFromInventory: () => writeCacheFromInventory,
|
|
34734
34734
|
writeJsonAtomic: () => writeJsonAtomic
|
|
34735
34735
|
});
|
|
34736
|
+
function isRecord(v) {
|
|
34737
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
34738
|
+
}
|
|
34739
|
+
function isStringArray(v) {
|
|
34740
|
+
return Array.isArray(v) && v.every((i) => typeof i === "string");
|
|
34741
|
+
}
|
|
34742
|
+
function isNumber(v) {
|
|
34743
|
+
return typeof v === "number" && Number.isFinite(v);
|
|
34744
|
+
}
|
|
34736
34745
|
function isStructurePattern(value) {
|
|
34737
|
-
if (
|
|
34738
|
-
|
|
34739
|
-
return typeof v.category === "string" && typeof v.name === "string" && Array.isArray(v.imports) && v.imports.every((i) => typeof i === "string") && typeof v.fileCount === "number";
|
|
34746
|
+
if (!isRecord(value)) return false;
|
|
34747
|
+
return typeof value.category === "string" && typeof value.name === "string" && isStringArray(value.imports) && isNumber(value.fileCount);
|
|
34740
34748
|
}
|
|
34741
34749
|
function isComponentFingerprint(value) {
|
|
34742
|
-
if (
|
|
34743
|
-
|
|
34744
|
-
|
|
34750
|
+
if (!isRecord(value)) return false;
|
|
34751
|
+
return typeof value.name === "string" && isStringArray(value.files) && typeof value.fingerprint === "string" && isStringArray(value.hooks) && isStringArray(value.props) && isNumber(value.line) && isNumber(value.endLine);
|
|
34752
|
+
}
|
|
34753
|
+
function isVersion3(value) {
|
|
34754
|
+
return value === STRUCTURE_SCHEMA_VERSION;
|
|
34745
34755
|
}
|
|
34746
34756
|
function isInventoryFile(value) {
|
|
34747
|
-
if (
|
|
34748
|
-
|
|
34749
|
-
|
|
34757
|
+
if (!isRecord(value)) return false;
|
|
34758
|
+
if (!isVersion3(value.version)) return false;
|
|
34759
|
+
if (typeof value.generatedAt !== "string") return false;
|
|
34760
|
+
if (typeof value.workspace !== "string") return false;
|
|
34761
|
+
if (!isNumber(value.scannedFiles)) return false;
|
|
34762
|
+
if (!isNumber(value.scanDurationMs)) return false;
|
|
34763
|
+
if (!Array.isArray(value.patterns) || !value.patterns.every(isStructurePattern)) return false;
|
|
34764
|
+
if (!Array.isArray(value.components) || !value.components.every(isComponentFingerprint)) return false;
|
|
34765
|
+
return true;
|
|
34750
34766
|
}
|
|
34751
34767
|
function isConstitutionFile(value) {
|
|
34752
|
-
if (
|
|
34753
|
-
|
|
34754
|
-
|
|
34768
|
+
if (!isRecord(value)) return false;
|
|
34769
|
+
if (!isVersion3(value.version)) return false;
|
|
34770
|
+
if (typeof value.generatedAt !== "string") return false;
|
|
34771
|
+
if (typeof value.workspace !== "string") return false;
|
|
34772
|
+
if (!isRecord(value.declared)) return false;
|
|
34773
|
+
if (!isStringArray(value.forbidden)) return false;
|
|
34774
|
+
if (!isStringArray(value.forbiddenPrefixes)) return false;
|
|
34775
|
+
return true;
|
|
34755
34776
|
}
|
|
34756
34777
|
function isFileMtimeEntry(value) {
|
|
34757
|
-
if (
|
|
34758
|
-
|
|
34759
|
-
return typeof v.file === "string" && typeof v.mtimeMs === "number" && typeof v.hash === "string";
|
|
34778
|
+
if (!isRecord(value)) return false;
|
|
34779
|
+
return typeof value.file === "string" && isNumber(value.mtimeMs) && typeof value.hash === "string";
|
|
34760
34780
|
}
|
|
34761
34781
|
function isHealthFile(value) {
|
|
34762
|
-
if (
|
|
34763
|
-
|
|
34764
|
-
if (
|
|
34765
|
-
if (typeof
|
|
34766
|
-
if (
|
|
34767
|
-
if (
|
|
34768
|
-
if (
|
|
34769
|
-
if (
|
|
34770
|
-
if (
|
|
34771
|
-
|
|
34772
|
-
|
|
34773
|
-
if (
|
|
34774
|
-
if (
|
|
34775
|
-
if (
|
|
34776
|
-
if (
|
|
34777
|
-
|
|
34778
|
-
|
|
34779
|
-
|
|
34780
|
-
|
|
34781
|
-
|
|
34782
|
-
|
|
34783
|
-
if (
|
|
34784
|
-
|
|
34785
|
-
|
|
34786
|
-
|
|
34787
|
-
}
|
|
34788
|
-
if (v.scanDurationMs !== void 0 && typeof v.scanDurationMs !== "number") return false;
|
|
34782
|
+
if (!isRecord(value)) return false;
|
|
34783
|
+
if (!isVersion3(value.version)) return false;
|
|
34784
|
+
if (typeof value.generatedAt !== "string") return false;
|
|
34785
|
+
if (typeof value.workspace !== "string") return false;
|
|
34786
|
+
if (!isNumber(value.aiQuality)) return false;
|
|
34787
|
+
if (!isNumber(value.engineeringHygiene)) return false;
|
|
34788
|
+
if (!isNumber(value.security)) return false;
|
|
34789
|
+
if (!isNumber(value.repositoryHealth)) return false;
|
|
34790
|
+
if (!isRecord(value.issueCounts)) return false;
|
|
34791
|
+
const counts = value.issueCounts;
|
|
34792
|
+
if (!isNumber(counts.high)) return false;
|
|
34793
|
+
if (!isNumber(counts.medium)) return false;
|
|
34794
|
+
if (!isNumber(counts.low)) return false;
|
|
34795
|
+
if (value.slopIndex !== void 0 && !isNumber(value.slopIndex)) return false;
|
|
34796
|
+
if (value.categoryScores !== void 0) {
|
|
34797
|
+
if (!isRecord(value.categoryScores)) return false;
|
|
34798
|
+
for (const score of Object.values(value.categoryScores)) {
|
|
34799
|
+
if (!isNumber(score)) return false;
|
|
34800
|
+
}
|
|
34801
|
+
}
|
|
34802
|
+
if (value.constitutionDrift !== void 0 && !isNumber(value.constitutionDrift)) return false;
|
|
34803
|
+
if (value.topOffenseIds !== void 0) {
|
|
34804
|
+
if (!isStringArray(value.topOffenseIds)) return false;
|
|
34805
|
+
}
|
|
34806
|
+
if (value.scanDurationMs !== void 0 && !isNumber(value.scanDurationMs)) return false;
|
|
34789
34807
|
return true;
|
|
34790
34808
|
}
|
|
34791
34809
|
function inventoryPath(workspaceDir) {
|
|
@@ -36801,6 +36819,7 @@ var init_dist2 = __esm({
|
|
|
36801
36819
|
import_path3 = require("path");
|
|
36802
36820
|
import_crypto2 = require("crypto");
|
|
36803
36821
|
init_dist();
|
|
36822
|
+
init_dist();
|
|
36804
36823
|
import_crypto3 = require("crypto");
|
|
36805
36824
|
import_promises2 = require("fs/promises");
|
|
36806
36825
|
import_path4 = require("path");
|
|
@@ -36812,7 +36831,11 @@ var init_dist2 = __esm({
|
|
|
36812
36831
|
RECALL_FLOOR = 1e-6;
|
|
36813
36832
|
LLR_CAP = 13.8;
|
|
36814
36833
|
DEFAULT_PRIOR_PREVALENCE = 0.3;
|
|
36815
|
-
ELIGIBLE_VERDICTS =
|
|
36834
|
+
ELIGIBLE_VERDICTS = new Set(
|
|
36835
|
+
["USEFUL", "OK", "NOISY", "INVERTED", "HYGIENE", "DORMANT"].filter(
|
|
36836
|
+
(v) => v !== "HYGIENE" && !isDefaultOff(v)
|
|
36837
|
+
)
|
|
36838
|
+
);
|
|
36816
36839
|
SUFFIXES_TO_STRIP = [
|
|
36817
36840
|
"RepositoryClient",
|
|
36818
36841
|
"ServiceFactory",
|
|
@@ -37652,7 +37675,7 @@ var init_math_gini_class_usage = __esm({
|
|
|
37652
37675
|
if (g < 0.5) return issues;
|
|
37653
37676
|
const sorted = [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
|
|
37654
37677
|
const topStr = sorted.map(([k, v]) => `${k}\xD7${v}`).join(", ");
|
|
37655
|
-
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] : { line: 1, column: 1 };
|
|
37678
|
+
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 } : { line: 1, column: 1 };
|
|
37656
37679
|
issues.push({
|
|
37657
37680
|
ruleId: "logic/math-gini-class-usage",
|
|
37658
37681
|
category: "logic",
|
|
@@ -39912,11 +39935,11 @@ function coveredFunctionNames(names, testFileSources, cwd) {
|
|
|
39912
39935
|
}
|
|
39913
39936
|
return covered;
|
|
39914
39937
|
}
|
|
39915
|
-
var
|
|
39938
|
+
var import_core4, import_node_fs10, MAX_PER_FILE, missingEdgeCaseRule;
|
|
39916
39939
|
var init_missing_edge_case = __esm({
|
|
39917
39940
|
"src/rules/test/missing-edge-case.ts"() {
|
|
39918
39941
|
"use strict";
|
|
39919
|
-
|
|
39942
|
+
import_core4 = require("@swc/core");
|
|
39920
39943
|
import_node_fs10 = require("fs");
|
|
39921
39944
|
init_rule();
|
|
39922
39945
|
MAX_PER_FILE = 20;
|
|
@@ -39961,7 +39984,7 @@ var init_missing_edge_case = __esm({
|
|
|
39961
39984
|
if (!source) return issues;
|
|
39962
39985
|
let ast;
|
|
39963
39986
|
try {
|
|
39964
|
-
ast = (0,
|
|
39987
|
+
ast = (0, import_core4.parseSync)(source, {
|
|
39965
39988
|
syntax: "typescript",
|
|
39966
39989
|
tsx: filePath.endsWith("tsx") || filePath.endsWith("jsx"),
|
|
39967
39990
|
target: "es2022"
|
|
@@ -40955,7 +40978,7 @@ var init_math_font_entropy = __esm({
|
|
|
40955
40978
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
40956
40979
|
if (total < 6) return issues;
|
|
40957
40980
|
if (h > 1.4) return issues;
|
|
40958
|
-
const anchor = flatClassNames(facts.v2)[0];
|
|
40981
|
+
const anchor = flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 };
|
|
40959
40982
|
issues.push({
|
|
40960
40983
|
ruleId: "visual/math-font-entropy",
|
|
40961
40984
|
category: "visual",
|
|
@@ -41095,7 +41118,7 @@ var init_math_rounded_entropy = __esm({
|
|
|
41095
41118
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
41096
41119
|
if (total < 6) return issues;
|
|
41097
41120
|
if (h > 1.8) return issues;
|
|
41098
|
-
const anchor = flatClassNames(facts.v2)[0];
|
|
41121
|
+
const anchor = flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 };
|
|
41099
41122
|
issues.push({
|
|
41100
41123
|
ruleId: "visual/math-rounded-entropy",
|
|
41101
41124
|
category: "visual",
|
|
@@ -41143,7 +41166,7 @@ var init_math_spacing_entropy = __esm({
|
|
|
41143
41166
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
41144
41167
|
if (total < 10) return issues;
|
|
41145
41168
|
if (h > 1.5) return issues;
|
|
41146
|
-
const anchor = flatClassNames(facts.v2)[0];
|
|
41169
|
+
const anchor = flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 };
|
|
41147
41170
|
issues.push({
|
|
41148
41171
|
ruleId: "visual/math-spacing-entropy",
|
|
41149
41172
|
category: "visual",
|
|
@@ -48206,7 +48229,7 @@ function confirmMagicRateLiteral(line) {
|
|
|
48206
48229
|
const probe = `let __probe = (${line});`;
|
|
48207
48230
|
let ast;
|
|
48208
48231
|
try {
|
|
48209
|
-
ast = (0,
|
|
48232
|
+
ast = (0, import_core6.parseSync)(probe, { syntax: "ecmascript", target: "es2022" });
|
|
48210
48233
|
} catch {
|
|
48211
48234
|
return true;
|
|
48212
48235
|
}
|
|
@@ -48485,11 +48508,11 @@ function extractIdentifier(line) {
|
|
|
48485
48508
|
const m = line.match(/Math\.round\s*\(\s*([A-Za-z_$][\w$.]*)/);
|
|
48486
48509
|
return m ? m[1] ?? "" : "<expr>";
|
|
48487
48510
|
}
|
|
48488
|
-
var
|
|
48511
|
+
var import_core6, BUSINESS_LOGIC_WEIGHTS, CURRENCY_IDENTIFIERS, COMMON_RATE_LITERALS, MATH_ROUND_CENTS, MAGIC_RATE_DECIMAL, HARDCODED_CURRENCY_SYMBOL, SOURCE_EXTENSION, ZOD_STRING, ZOD_STRING_CALL, REQUIRED_ERROR, INVALID_TYPE_ERROR, HARDCODED_ISO_DATE, LOCALE_STRING_NO_OPTIONS, RAW_CURRENCY_IN_TEMPLATE;
|
|
48489
48512
|
var init_business_logic = __esm({
|
|
48490
48513
|
"src/engine/business-logic.ts"() {
|
|
48491
48514
|
"use strict";
|
|
48492
|
-
|
|
48515
|
+
import_core6 = require("@swc/core");
|
|
48493
48516
|
BUSINESS_LOGIC_WEIGHTS = {
|
|
48494
48517
|
pricing: 3,
|
|
48495
48518
|
validation: 2,
|
|
@@ -49860,6 +49883,13 @@ function mergeComponentsByName(components) {
|
|
|
49860
49883
|
}
|
|
49861
49884
|
byName.set(c.name, {
|
|
49862
49885
|
...c,
|
|
49886
|
+
// All visitors (rust.ts, php.ts, go.ts, …) push Components with
|
|
49887
|
+
// `files: [filePath]` — non-empty by construction. The JSON
|
|
49888
|
+
// Schema (inventory.schema.json) requires `files` to be
|
|
49889
|
+
// `[string, ...string[]]` (at least 1); the cast is safe under
|
|
49890
|
+
// the visitor invariant. If a future visitor ever produces an
|
|
49891
|
+
// empty files array, the runtime validator
|
|
49892
|
+
// (`isInventoryFile`) will reject the artifact at write time.
|
|
49863
49893
|
files: c.files.slice(),
|
|
49864
49894
|
hooks: c.hooks.slice(),
|
|
49865
49895
|
props: c.props.slice()
|
|
@@ -55053,7 +55083,7 @@ function promptMultiSelect(rl, question, options, defaultValue) {
|
|
|
55053
55083
|
resolve18([]);
|
|
55054
55084
|
return;
|
|
55055
55085
|
}
|
|
55056
|
-
const selected = [...new Set(numbers.map((n) => options[n - 2]))];
|
|
55086
|
+
const selected = [...new Set(numbers.map((n) => options[n - 2]).filter((v) => v !== void 0))];
|
|
55057
55087
|
resolve18(selected);
|
|
55058
55088
|
});
|
|
55059
55089
|
}
|
package/dist/index.js
CHANGED
|
@@ -30235,7 +30235,7 @@ var init_math_element_uniformity = __esm({
|
|
|
30235
30235
|
if (!anchor) anchor = { line: el.line, column: el.column };
|
|
30236
30236
|
}
|
|
30237
30237
|
}
|
|
30238
|
-
const values = [counts.button, counts.input, counts.select].filter((v) => v > 0);
|
|
30238
|
+
const values = [counts.button, counts.input, counts.select].filter((v) => typeof v === "number" && v > 0);
|
|
30239
30239
|
if (values.length < 2) return issues;
|
|
30240
30240
|
const max = Math.max(...values);
|
|
30241
30241
|
const min = Math.min(...values);
|
|
@@ -30293,7 +30293,7 @@ var init_math_grid_uniformity = __esm({
|
|
|
30293
30293
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
30294
30294
|
if (total < 4) return issues;
|
|
30295
30295
|
if (h > 1) return issues;
|
|
30296
|
-
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] : { line: 1, column: 1 };
|
|
30296
|
+
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 } : { line: 1, column: 1 };
|
|
30297
30297
|
issues.push({
|
|
30298
30298
|
ruleId: "layout/math-grid-uniformity",
|
|
30299
30299
|
category: "layout",
|
|
@@ -34728,59 +34728,77 @@ __export(dist_exports, {
|
|
|
34728
34728
|
});
|
|
34729
34729
|
import { writeFileSync, renameSync, existsSync as existsSync8, readFileSync as readFileSync9, statSync as statSync4, mkdirSync } from "fs";
|
|
34730
34730
|
import { join as join9, dirname as dirname5 } from "path";
|
|
34731
|
+
function isRecord(v) {
|
|
34732
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
34733
|
+
}
|
|
34734
|
+
function isStringArray(v) {
|
|
34735
|
+
return Array.isArray(v) && v.every((i) => typeof i === "string");
|
|
34736
|
+
}
|
|
34737
|
+
function isNumber(v) {
|
|
34738
|
+
return typeof v === "number" && Number.isFinite(v);
|
|
34739
|
+
}
|
|
34731
34740
|
function isStructurePattern(value) {
|
|
34732
|
-
if (
|
|
34733
|
-
|
|
34734
|
-
return typeof v.category === "string" && typeof v.name === "string" && Array.isArray(v.imports) && v.imports.every((i) => typeof i === "string") && typeof v.fileCount === "number";
|
|
34741
|
+
if (!isRecord(value)) return false;
|
|
34742
|
+
return typeof value.category === "string" && typeof value.name === "string" && isStringArray(value.imports) && isNumber(value.fileCount);
|
|
34735
34743
|
}
|
|
34736
34744
|
function isComponentFingerprint(value) {
|
|
34737
|
-
if (
|
|
34738
|
-
|
|
34739
|
-
|
|
34745
|
+
if (!isRecord(value)) return false;
|
|
34746
|
+
return typeof value.name === "string" && isStringArray(value.files) && typeof value.fingerprint === "string" && isStringArray(value.hooks) && isStringArray(value.props) && isNumber(value.line) && isNumber(value.endLine);
|
|
34747
|
+
}
|
|
34748
|
+
function isVersion3(value) {
|
|
34749
|
+
return value === STRUCTURE_SCHEMA_VERSION;
|
|
34740
34750
|
}
|
|
34741
34751
|
function isInventoryFile(value) {
|
|
34742
|
-
if (
|
|
34743
|
-
|
|
34744
|
-
|
|
34752
|
+
if (!isRecord(value)) return false;
|
|
34753
|
+
if (!isVersion3(value.version)) return false;
|
|
34754
|
+
if (typeof value.generatedAt !== "string") return false;
|
|
34755
|
+
if (typeof value.workspace !== "string") return false;
|
|
34756
|
+
if (!isNumber(value.scannedFiles)) return false;
|
|
34757
|
+
if (!isNumber(value.scanDurationMs)) return false;
|
|
34758
|
+
if (!Array.isArray(value.patterns) || !value.patterns.every(isStructurePattern)) return false;
|
|
34759
|
+
if (!Array.isArray(value.components) || !value.components.every(isComponentFingerprint)) return false;
|
|
34760
|
+
return true;
|
|
34745
34761
|
}
|
|
34746
34762
|
function isConstitutionFile(value) {
|
|
34747
|
-
if (
|
|
34748
|
-
|
|
34749
|
-
|
|
34763
|
+
if (!isRecord(value)) return false;
|
|
34764
|
+
if (!isVersion3(value.version)) return false;
|
|
34765
|
+
if (typeof value.generatedAt !== "string") return false;
|
|
34766
|
+
if (typeof value.workspace !== "string") return false;
|
|
34767
|
+
if (!isRecord(value.declared)) return false;
|
|
34768
|
+
if (!isStringArray(value.forbidden)) return false;
|
|
34769
|
+
if (!isStringArray(value.forbiddenPrefixes)) return false;
|
|
34770
|
+
return true;
|
|
34750
34771
|
}
|
|
34751
34772
|
function isFileMtimeEntry(value) {
|
|
34752
|
-
if (
|
|
34753
|
-
|
|
34754
|
-
return typeof v.file === "string" && typeof v.mtimeMs === "number" && typeof v.hash === "string";
|
|
34773
|
+
if (!isRecord(value)) return false;
|
|
34774
|
+
return typeof value.file === "string" && isNumber(value.mtimeMs) && typeof value.hash === "string";
|
|
34755
34775
|
}
|
|
34756
34776
|
function isHealthFile(value) {
|
|
34757
|
-
if (
|
|
34758
|
-
|
|
34759
|
-
if (
|
|
34760
|
-
if (typeof
|
|
34761
|
-
if (
|
|
34762
|
-
if (
|
|
34763
|
-
if (
|
|
34764
|
-
if (
|
|
34765
|
-
if (
|
|
34766
|
-
|
|
34767
|
-
|
|
34768
|
-
if (
|
|
34769
|
-
if (
|
|
34770
|
-
if (
|
|
34771
|
-
if (
|
|
34772
|
-
|
|
34773
|
-
|
|
34774
|
-
|
|
34775
|
-
|
|
34776
|
-
|
|
34777
|
-
|
|
34778
|
-
if (
|
|
34779
|
-
|
|
34780
|
-
|
|
34781
|
-
|
|
34782
|
-
}
|
|
34783
|
-
if (v.scanDurationMs !== void 0 && typeof v.scanDurationMs !== "number") return false;
|
|
34777
|
+
if (!isRecord(value)) return false;
|
|
34778
|
+
if (!isVersion3(value.version)) return false;
|
|
34779
|
+
if (typeof value.generatedAt !== "string") return false;
|
|
34780
|
+
if (typeof value.workspace !== "string") return false;
|
|
34781
|
+
if (!isNumber(value.aiQuality)) return false;
|
|
34782
|
+
if (!isNumber(value.engineeringHygiene)) return false;
|
|
34783
|
+
if (!isNumber(value.security)) return false;
|
|
34784
|
+
if (!isNumber(value.repositoryHealth)) return false;
|
|
34785
|
+
if (!isRecord(value.issueCounts)) return false;
|
|
34786
|
+
const counts = value.issueCounts;
|
|
34787
|
+
if (!isNumber(counts.high)) return false;
|
|
34788
|
+
if (!isNumber(counts.medium)) return false;
|
|
34789
|
+
if (!isNumber(counts.low)) return false;
|
|
34790
|
+
if (value.slopIndex !== void 0 && !isNumber(value.slopIndex)) return false;
|
|
34791
|
+
if (value.categoryScores !== void 0) {
|
|
34792
|
+
if (!isRecord(value.categoryScores)) return false;
|
|
34793
|
+
for (const score of Object.values(value.categoryScores)) {
|
|
34794
|
+
if (!isNumber(score)) return false;
|
|
34795
|
+
}
|
|
34796
|
+
}
|
|
34797
|
+
if (value.constitutionDrift !== void 0 && !isNumber(value.constitutionDrift)) return false;
|
|
34798
|
+
if (value.topOffenseIds !== void 0) {
|
|
34799
|
+
if (!isStringArray(value.topOffenseIds)) return false;
|
|
34800
|
+
}
|
|
34801
|
+
if (value.scanDurationMs !== void 0 && !isNumber(value.scanDurationMs)) return false;
|
|
34784
34802
|
return true;
|
|
34785
34803
|
}
|
|
34786
34804
|
function inventoryPath(workspaceDir) {
|
|
@@ -36797,6 +36815,7 @@ var init_dist2 = __esm({
|
|
|
36797
36815
|
"../engine/dist/index.js"() {
|
|
36798
36816
|
"use strict";
|
|
36799
36817
|
init_dist();
|
|
36818
|
+
init_dist();
|
|
36800
36819
|
SMOOTHING = 0.5;
|
|
36801
36820
|
DEFAULT_PRIOR = { pAI: 0.5, pHuman: 0.5 };
|
|
36802
36821
|
TELEMETRY_FILE = join22(".slopbrick", "structure.json");
|
|
@@ -36805,7 +36824,11 @@ var init_dist2 = __esm({
|
|
|
36805
36824
|
RECALL_FLOOR = 1e-6;
|
|
36806
36825
|
LLR_CAP = 13.8;
|
|
36807
36826
|
DEFAULT_PRIOR_PREVALENCE = 0.3;
|
|
36808
|
-
ELIGIBLE_VERDICTS =
|
|
36827
|
+
ELIGIBLE_VERDICTS = new Set(
|
|
36828
|
+
["USEFUL", "OK", "NOISY", "INVERTED", "HYGIENE", "DORMANT"].filter(
|
|
36829
|
+
(v) => v !== "HYGIENE" && !isDefaultOff(v)
|
|
36830
|
+
)
|
|
36831
|
+
);
|
|
36809
36832
|
SUFFIXES_TO_STRIP = [
|
|
36810
36833
|
"RepositoryClient",
|
|
36811
36834
|
"ServiceFactory",
|
|
@@ -37645,7 +37668,7 @@ var init_math_gini_class_usage = __esm({
|
|
|
37645
37668
|
if (g < 0.5) return issues;
|
|
37646
37669
|
const sorted = [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
|
|
37647
37670
|
const topStr = sorted.map(([k, v]) => `${k}\xD7${v}`).join(", ");
|
|
37648
|
-
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] : { line: 1, column: 1 };
|
|
37671
|
+
const anchor = facts.v2 ? flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 } : { line: 1, column: 1 };
|
|
37649
37672
|
issues.push({
|
|
37650
37673
|
ruleId: "logic/math-gini-class-usage",
|
|
37651
37674
|
category: "logic",
|
|
@@ -40948,7 +40971,7 @@ var init_math_font_entropy = __esm({
|
|
|
40948
40971
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
40949
40972
|
if (total < 6) return issues;
|
|
40950
40973
|
if (h > 1.4) return issues;
|
|
40951
|
-
const anchor = flatClassNames(facts.v2)[0];
|
|
40974
|
+
const anchor = flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 };
|
|
40952
40975
|
issues.push({
|
|
40953
40976
|
ruleId: "visual/math-font-entropy",
|
|
40954
40977
|
category: "visual",
|
|
@@ -41088,7 +41111,7 @@ var init_math_rounded_entropy = __esm({
|
|
|
41088
41111
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
41089
41112
|
if (total < 6) return issues;
|
|
41090
41113
|
if (h > 1.8) return issues;
|
|
41091
|
-
const anchor = flatClassNames(facts.v2)[0];
|
|
41114
|
+
const anchor = flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 };
|
|
41092
41115
|
issues.push({
|
|
41093
41116
|
ruleId: "visual/math-rounded-entropy",
|
|
41094
41117
|
category: "visual",
|
|
@@ -41136,7 +41159,7 @@ var init_math_spacing_entropy = __esm({
|
|
|
41136
41159
|
const { h, vocab, total } = shannonEntropy(counts);
|
|
41137
41160
|
if (total < 10) return issues;
|
|
41138
41161
|
if (h > 1.5) return issues;
|
|
41139
|
-
const anchor = flatClassNames(facts.v2)[0];
|
|
41162
|
+
const anchor = flatClassNames(facts.v2)[0] ?? { line: 1, column: 1 };
|
|
41140
41163
|
issues.push({
|
|
41141
41164
|
ruleId: "visual/math-spacing-entropy",
|
|
41142
41165
|
category: "visual",
|
|
@@ -49859,6 +49882,13 @@ function mergeComponentsByName(components) {
|
|
|
49859
49882
|
}
|
|
49860
49883
|
byName.set(c.name, {
|
|
49861
49884
|
...c,
|
|
49885
|
+
// All visitors (rust.ts, php.ts, go.ts, …) push Components with
|
|
49886
|
+
// `files: [filePath]` — non-empty by construction. The JSON
|
|
49887
|
+
// Schema (inventory.schema.json) requires `files` to be
|
|
49888
|
+
// `[string, ...string[]]` (at least 1); the cast is safe under
|
|
49889
|
+
// the visitor invariant. If a future visitor ever produces an
|
|
49890
|
+
// empty files array, the runtime validator
|
|
49891
|
+
// (`isInventoryFile`) will reject the artifact at write time.
|
|
49862
49892
|
files: c.files.slice(),
|
|
49863
49893
|
hooks: c.hooks.slice(),
|
|
49864
49894
|
props: c.props.slice()
|
|
@@ -54972,7 +55002,7 @@ function promptMultiSelect(rl, question, options, defaultValue) {
|
|
|
54972
55002
|
resolve18([]);
|
|
54973
55003
|
return;
|
|
54974
55004
|
}
|
|
54975
|
-
const selected = [...new Set(numbers.map((n) => options[n - 2]))];
|
|
55005
|
+
const selected = [...new Set(numbers.map((n) => options[n - 2]).filter((v) => v !== void 0))];
|
|
54976
55006
|
resolve18(selected);
|
|
54977
55007
|
});
|
|
54978
55008
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slopbrick",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.4",
|
|
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": {
|