@afokapu/atdd-bun 0.10.66 → 0.10.68
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/README.md +2 -2
- package/detectors/bun_clean_architecture_detector/detect.mjs +30 -13
- package/detectors/bun_design_system_detector/detect.mjs +30 -13
- package/detectors/bun_fullstack_detector/detect.mjs +30 -13
- package/detectors/bun_green_traceability_detector/detect.mjs +30 -13
- package/detectors/bun_interlocking_coverage/detect.mjs +30 -13
- package/detectors/bun_interlocking_infrastructure/detect.mjs +30 -13
- package/detectors/bun_responsive_detector/detect.mjs +30 -13
- package/detectors/bun_security_hygiene_detector/detect.mjs +30 -13
- package/detectors/bun_telemetry_code/detect.mjs +34 -24
- package/detectors/bun_telemetry_test/detect.mjs +34 -24
- package/detectors/bun_tester_discipline_detector/detect.mjs +30 -13
- package/detectors/bun_ts_metrics_detector/detect.mjs +30 -13
- package/detectors/htmx_e2e_detector/detect.mjs +30 -13
- package/detectors/htmx_hypermedia_detector/detect.mjs +30 -13
- package/detectors/htmx_tester_detector/detect.mjs +30 -13
- package/integrity.json +20 -20
- package/package.json +1 -1
- package/src/ci.ts +7 -1
- package/src/cli.ts +1 -1
- package/templates/github/atdd-bun.yml +4 -5
package/README.md
CHANGED
|
@@ -155,7 +155,7 @@ bun run atdd-bun coder tester --ratchet --base <40-character-reviewed-main-sha>
|
|
|
155
155
|
|
|
156
156
|
The command runs the same installed detectors against an isolated exact base and the clean candidate, emits a redacted JSON `carried`/`new`/`resolved` fingerprint report, and never writes or accepts a baseline. `report` records debt without changing command success; `reject-new` exits non-zero only when the candidate adds a finding absent from the equivalent base. The declared `ratchet.profiles` must exactly match the command's effective profiles. Base and candidate profile/context digests must match or comparison fails closed; profile/config adoption is separately governed. Use debt-remediation branches to remove carried findings. Direct implementation profiles can opt in only through this explicit policy and do not alter configured merge profiles or `profiles:`.
|
|
157
157
|
|
|
158
|
-
Fingerprints are SHA-256 of a versioned rule, normalized repository-relative path, and semantic subject where supplied; line/column, rendered evidence, source text, absolute paths, and runtime data are excluded. Ratchet findings are unrelated to Bun `test.failing()` or JUnit/behavioral-test baselines.
|
|
158
|
+
Fingerprints are SHA-256 of a versioned rule, normalized repository-relative path, and semantic subject where supplied; line/column, rendered evidence, source text, absolute paths, and runtime data are excluded. Ratchet findings are unrelated to Bun `test.failing()` or JUnit/behavioral-test baselines. Generated Provider CI uses this exact command when the generated policy is `reject-new`, against the pull request base object, pre-push tip, or merge-queue target, with full-history checkout; it rejects an absent, zero, invalid, unavailable, or non-ancestor base. Without that policy, generated CI retains strict `all` enforcement.
|
|
159
159
|
|
|
160
160
|
### One-time explicit profile activation
|
|
161
161
|
|
|
@@ -165,7 +165,7 @@ When an existing exact main has debt under a smaller explicit profile list, a se
|
|
|
165
165
|
bun run atdd-bun --profile flow,traceability --ratchet --ratchet-activate-profiles --base <40-character-reviewed-main-sha>
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
-
This is an activation-only exception to the ordinary equal-context rule, not a baseline migration. It requires an explicit candidate `profiles:` list, a base whose effective profile set (its explicit list, or the implicit default set when it has none) is a strict subset of it, and identical non-profile policy/configuration. A removal, implicit/default-list candidate adoption, unrelated configuration change, dirty tree, unavailable/non-ancestor base, or omission of `--ratchet-activate-profiles` fails closed. The command stores no activation state or accepted findings; after the governed expansion lands, use ordinary `--ratchet` with exact matching context. Strict non-ratchet enforcement remains unchanged.
|
|
168
|
+
This is an activation-only exception to the ordinary equal-context rule, not a baseline migration. It requires an explicit candidate `profiles:` list, a base whose effective profile set (its explicit list, or the implicit default set when it has none) is a strict subset of it, and identical non-profile policy/configuration. An unchanged matching configuration may also carry the flag and follows the ordinary exact-context comparison, letting generated CI use one command for active and expanded policies. A removal, implicit/default-list candidate adoption, unrelated configuration change, dirty tree, unavailable/non-ancestor base, or omission of `--ratchet-activate-profiles` for an expansion fails closed. The command stores no activation state or accepted findings; after the governed expansion lands, use ordinary `--ratchet` with exact matching context. Strict non-ratchet enforcement remains unchanged.
|
|
169
169
|
|
|
170
170
|
### Generated exact-base commit gate
|
|
171
171
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family bun_clean_architecture_detector: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family bun_clean_architecture_detector: " + out.length + " violation(s)\n");
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family bun_design_system_detector: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family bun_design_system_detector: " + out.length + " violation(s)\n");
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family bun_fullstack_detector: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family bun_fullstack_detector: " + out.length + " violation(s)\n");
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family bun_green_traceability_detector: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family bun_green_traceability_detector: " + out.length + " violation(s)\n");
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-ilc-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family bun_interlocking_coverage: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family bun_interlocking_coverage: " + out.length + " violation(s)\n");
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-il-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family bun_interlocking_infrastructure: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family bun_interlocking_infrastructure: " + out.length + " violation(s)\n");
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family bun_responsive_detector: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family bun_responsive_detector: " + out.length + " violation(s)\n");
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family bun_security_hygiene_detector: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family bun_security_hygiene_detector: " + out.length + " violation(s)\n");
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// RAW v1.1 reports into one — one implementation realizing a family of rule_ids.
|
|
5
5
|
// Files whose name begins with `_` are skipped: they are shared helpers.
|
|
6
6
|
import { execFileSync } from "node:child_process";
|
|
7
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
7
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
import { join, dirname } from "node:path";
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
@@ -20,31 +20,41 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
20
20
|
.sort();
|
|
21
21
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
22
22
|
const out = [];
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
23
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
24
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
25
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
26
|
+
const failures = [];
|
|
27
|
+
try {
|
|
28
|
+
for (const c of checks) {
|
|
29
|
+
const rep = join(td, c + ".json");
|
|
30
|
+
try {
|
|
31
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
32
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
33
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
34
|
+
});
|
|
35
|
+
} catch (error) {
|
|
36
|
+
const why = error instanceof Error ? error.message.split("\n")[0] : String(error);
|
|
37
|
+
// Keep the established wording for the crash-without-a-report case (tests/telemetry-review.test.ts #6).
|
|
38
|
+
let reported = true;
|
|
39
|
+
try { readFileSync(rep, "utf8"); } catch { reported = false; }
|
|
40
|
+
failures.push(reported ? `member ${c} failed to run: ${why}` : `member ${c} crashed without a violation report: ${why}`);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
45
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
46
|
+
out.push(...report.violations);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
49
|
+
}
|
|
45
50
|
}
|
|
51
|
+
} finally {
|
|
52
|
+
rmSync(td, { recursive: true, force: true });
|
|
53
|
+
}
|
|
54
|
+
if (failures.length) {
|
|
55
|
+
for (const failure of failures) process.stderr.write("family bun_telemetry_code: " + failure + "\n");
|
|
56
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
46
57
|
}
|
|
47
|
-
if (crashed) process.exit(2); // a crashed member is a detector bug: fail loudly, not silently
|
|
48
58
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
49
59
|
process.stderr.write("family bun_telemetry_code: " + out.length + " violation(s)\n");
|
|
50
60
|
process.exit(0);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// RAW v1.1 reports into one — one implementation realizing a family of rule_ids.
|
|
5
5
|
// Files whose name begins with `_` are skipped: they are shared helpers.
|
|
6
6
|
import { execFileSync } from "node:child_process";
|
|
7
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
7
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
import { join, dirname } from "node:path";
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
@@ -20,31 +20,41 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
20
20
|
.sort();
|
|
21
21
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
22
22
|
const out = [];
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
23
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
24
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
25
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
26
|
+
const failures = [];
|
|
27
|
+
try {
|
|
28
|
+
for (const c of checks) {
|
|
29
|
+
const rep = join(td, c + ".json");
|
|
30
|
+
try {
|
|
31
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
32
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
33
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
34
|
+
});
|
|
35
|
+
} catch (error) {
|
|
36
|
+
const why = error instanceof Error ? error.message.split("\n")[0] : String(error);
|
|
37
|
+
// Keep the established wording for the crash-without-a-report case (tests/telemetry-review.test.ts #6).
|
|
38
|
+
let reported = true;
|
|
39
|
+
try { readFileSync(rep, "utf8"); } catch { reported = false; }
|
|
40
|
+
failures.push(reported ? `member ${c} failed to run: ${why}` : `member ${c} crashed without a violation report: ${why}`);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
45
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
46
|
+
out.push(...report.violations);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
49
|
+
}
|
|
45
50
|
}
|
|
51
|
+
} finally {
|
|
52
|
+
rmSync(td, { recursive: true, force: true });
|
|
53
|
+
}
|
|
54
|
+
if (failures.length) {
|
|
55
|
+
for (const failure of failures) process.stderr.write("family bun_telemetry_test: " + failure + "\n");
|
|
56
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
46
57
|
}
|
|
47
|
-
if (crashed) process.exit(2); // a crashed member is a detector bug: fail loudly, not silently
|
|
48
58
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
49
59
|
process.stderr.write("family bun_telemetry_test: " + out.length + " violation(s)\n");
|
|
50
60
|
process.exit(0);
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family bun_tester_discipline_detector: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family bun_tester_discipline_detector: " + out.length + " violation(s)\n");
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family bun_ts_metrics_detector: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family bun_ts_metrics_detector: " + out.length + " violation(s)\n");
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family htmx_e2e_detector: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family htmx_e2e_detector: " + out.length + " violation(s)\n");
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family htmx_hypermedia_detector: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family htmx_hypermedia_detector: " + out.length + " violation(s)\n");
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// their checks re-implements its own walker; this provider factors the walk into
|
|
12
12
|
// lib/scan.mjs instead.)
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { readFileSync, writeFileSync, mkdtempSync, readdirSync } from "node:fs";
|
|
14
|
+
import { readFileSync, writeFileSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
@@ -27,19 +27,36 @@ const checks = readdirSync(join(here, "checks"))
|
|
|
27
27
|
.sort();
|
|
28
28
|
const td = mkdtempSync(join(tmpdir(), "atdd-bun-fam-"));
|
|
29
29
|
const out = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
// FAIL CLOSED. A member that cannot run (crash, non-zero exit) or leaves no usable report is a detector
|
|
31
|
+
// failure, never "zero findings": in a ratchet a silent zero on the candidate side reads as resolved debt and
|
|
32
|
+
// masks genuinely new findings. A member that ran and found nothing writes {"violations": []} and passes.
|
|
33
|
+
const failures = [];
|
|
34
|
+
try {
|
|
35
|
+
for (const c of checks) {
|
|
36
|
+
const rep = join(td, c + ".json");
|
|
37
|
+
try {
|
|
38
|
+
execFileSync(process.execPath, [join(here, "checks", c)], {
|
|
39
|
+
env: { ...process.env, ATDD_VIOLATIONS_REPORT: rep },
|
|
40
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures.push(`member ${c} failed to run: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const report = JSON.parse(readFileSync(rep, "utf8"));
|
|
48
|
+
if (!report || !Array.isArray(report.violations)) throw new Error("report has no violations array");
|
|
49
|
+
out.push(...report.violations);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
failures.push(`member ${c} left no usable violation report: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(td, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
if (failures.length) {
|
|
58
|
+
for (const failure of failures) process.stderr.write("family htmx_tester_detector: " + failure + "\n");
|
|
59
|
+
process.exit(2); // the run failed: the caller must report a failure, not a verdict
|
|
43
60
|
}
|
|
44
61
|
writeFileSync(reportPath, JSON.stringify({ violations: out }, null, 2), "utf8");
|
|
45
62
|
process.stderr.write("family htmx_tester_detector: " + out.length + " violation(s)\n");
|
package/integrity.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.10.
|
|
2
|
+
"version": "0.10.68",
|
|
3
3
|
"files": {
|
|
4
4
|
"HOOK_AUDIT.md": "5329d840db37671b1918f688ead26865473b87db73dbc75f7c8b2a8bbe8d6d43",
|
|
5
5
|
"PLANNER_PORT.md": "fb5935bac8b7ac18994de21e43ace3a5ef8cd55f85b0e3349fca261280054f11",
|
|
6
|
-
"README.md": "
|
|
6
|
+
"README.md": "8f0e45595fc10bb6f033b81b67246e57bb3f5bbaf62b35ba950beb5f9f82a938",
|
|
7
7
|
"bunfig.toml": "b9fc65eca9014c5179380259d70e76385a6a80788fa9a2df5fb3eaa5554fd2fe",
|
|
8
8
|
"conventions/_profiles/architecture.yaml": "f1808768b720a4e476047e4a0912002ca673946562cea9aeef5d0c214828d93a",
|
|
9
9
|
"conventions/_profiles/coder.yaml": "3fb191556a64c9ebcf249516afa189afca24da9b22fd40b2fc66908196cdfb78",
|
|
@@ -214,7 +214,7 @@
|
|
|
214
214
|
"detectors/bun_clean_architecture_detector/checks/a_dto_purity.mjs": "9881a38e853136c905d4e9794b9bbbc90c8e854af14fb70d1d0c606d0698636a",
|
|
215
215
|
"detectors/bun_clean_architecture_detector/checks/a_hierarchy_import.mjs": "e6e150d787565eb47931235e7126f9e67cfd055c25f2153725d4d47cc282f4f9",
|
|
216
216
|
"detectors/bun_clean_architecture_detector/checks/a_layer_naming.mjs": "e63a57988cec9661977231c89b81abc7dac0d807e6409cd118bb78db2acdbae0",
|
|
217
|
-
"detectors/bun_clean_architecture_detector/detect.mjs": "
|
|
217
|
+
"detectors/bun_clean_architecture_detector/detect.mjs": "f076d10209676b19ae552f80c8651070591f3f56d4390d62eea8551fd8924362",
|
|
218
218
|
"detectors/bun_clean_architecture_detector/fixtures/clean/contracts/order.ts": "74447127b75f6fcb0e8ff9a86f64c65ce668775e25cbe5f328796c881c4d0d06",
|
|
219
219
|
"detectors/bun_clean_architecture_detector/fixtures/clean/features/orders/application/place.ts": "1bbbd5e42d39c7bf9ad0a347338a2e3a3ba35647ed20ab03bc43cdd50b2e73bd",
|
|
220
220
|
"detectors/bun_clean_architecture_detector/fixtures/clean/features/orders/composition.ts": "97d9dd022333f90c369dfdb381d7bb7eb12c05645b7fdffd0e98e8b5c9c2d34b",
|
|
@@ -241,7 +241,7 @@
|
|
|
241
241
|
"detectors/bun_design_system_detector/checks/design_token_hardcoded.mjs": "d5c800bacbb7eeb80e0cbc016e08bff99b4f6940b3e8704f19534daf2d58920f",
|
|
242
242
|
"detectors/bun_design_system_detector/checks/design_tokens_pure.mjs": "9fd668df42c7a6a7d7949bb5975ba3c6925abcb908d626a573f56800f96e32d9",
|
|
243
243
|
"detectors/bun_design_system_detector/checks/design_wagons_import.mjs": "5cbd9776bcc3defdd4f28cbc228b3164ef1a694c64c86b151a1cd67f9687dd21",
|
|
244
|
-
"detectors/bun_design_system_detector/detect.mjs": "
|
|
244
|
+
"detectors/bun_design_system_detector/detect.mjs": "f8eb9cda3e35b8a808614a9655fd80574e506d1a438fcc15e68c0b7fdd833dcc",
|
|
245
245
|
"detectors/bun_design_system_detector/fixtures/clean/app/public/index.html": "319db2e6317da873b974f27327514d4c3dcc996b0349603a5f62d32c4b93bd01",
|
|
246
246
|
"detectors/bun_design_system_detector/fixtures/clean/app/public/site.css": "6a38389455c6d653cbc641bf890f6d22c0c114fec9310d6625499613517d1ae4",
|
|
247
247
|
"detectors/bun_design_system_detector/fixtures/clean/app/src/design/components/Card.tsx": "2430640f08598aab578b00b7675367843b63154b5838020372ed82bb105eae67",
|
|
@@ -275,7 +275,7 @@
|
|
|
275
275
|
"detectors/bun_fullstack_detector/checks/bun_runtime_server_is_bun_serve.mjs": "0f241ddccf27a9315036f98671473ec359a70ef9fbddfcb450bcb82615a0d7dd",
|
|
276
276
|
"detectors/bun_fullstack_detector/checks/bun_runtime_single_lockfile.mjs": "7fa6d763152b6ee689ba9389934197330abb6739cbf9d749a266b79764b627ab",
|
|
277
277
|
"detectors/bun_fullstack_detector/checks/bun_runtime_typecheck_enforced.mjs": "1a11b16d9829dd438ae7bd5ecedf898916328b3ef52692bf43e7b13dc96a8c35",
|
|
278
|
-
"detectors/bun_fullstack_detector/detect.mjs": "
|
|
278
|
+
"detectors/bun_fullstack_detector/detect.mjs": "7a95ee4b9b87f445f32ad67e1bba8e4547241632366c02721591b514162c4ea9",
|
|
279
279
|
"detectors/bun_fullstack_detector/fixtures/clean/bun_runtime_server_is_bun_serve/server.ts": "dd5071ff5784794ee754a30e9b00bb6e4eb789a733eede6b5a12e071ae18e7ec",
|
|
280
280
|
"detectors/bun_fullstack_detector/fixtures/clean/bun_runtime_single_lockfile/bun.lock": "40902d700e59dd48c9def59f9a86378db1496f44267c49c1c9f97c55ef00792e",
|
|
281
281
|
"detectors/bun_fullstack_detector/fixtures/clean/bun_runtime_typecheck_enforced/package.json": "7e9ff5f6c0d2124cfa65323f103c62e0d6a23864a2ca7bd843020e926b56a9aa",
|
|
@@ -301,7 +301,7 @@
|
|
|
301
301
|
"detectors/bun_green_traceability_detector/checks/green_urn_pattern.mjs": "e4535307f5308baf9e23f4852bfc9cce833d38a98309c23f386431e8284e9d06",
|
|
302
302
|
"detectors/bun_green_traceability_detector/checks/green_urn_side.mjs": "432937ce891509b3f51d6e469fb77361acaa83739731ee272790d470c50186e0",
|
|
303
303
|
"detectors/bun_green_traceability_detector/checks/green_urn_wagon_feature.mjs": "1341e66efe3898c95dca0e09d603fd92e13eaabf4abaa4940d0c0f1154ff2fe0",
|
|
304
|
-
"detectors/bun_green_traceability_detector/detect.mjs": "
|
|
304
|
+
"detectors/bun_green_traceability_detector/detect.mjs": "0d93a7cffbc48d4647a5d5dd04a099583a4ed5692975029075242b8938ccca0d",
|
|
305
305
|
"detectors/bun_green_traceability_detector/fixtures/clean/green_header_order/OrderPanel.html": "e7c6e3d73188e0016f148381d1df189dbe5404f4b8d52d845060f90c12157d86",
|
|
306
306
|
"detectors/bun_green_traceability_detector/fixtures/clean/green_header_order/OrderRow.ts": "173b0fba0d39be44c39461b8b2e178148bbb93cd789871d5b6e77c69fcd19d7c",
|
|
307
307
|
"detectors/bun_green_traceability_detector/fixtures/clean/green_header_purpose/OrderPanel.html": "e7c6e3d73188e0016f148381d1df189dbe5404f4b8d52d845060f90c12157d86",
|
|
@@ -393,7 +393,7 @@
|
|
|
393
393
|
"detectors/bun_interlocking_coverage/checks/interlocking_smoke_coverage.mjs": "28e016e1a4cd394291640679876b16c7d6a725530c7fbfa4bd1da8a354ecff86",
|
|
394
394
|
"detectors/bun_interlocking_coverage/checks/interlocking_trace_binds.mjs": "1cc3a11d50a075f3211a6d9cbf27aafcbf7e77b6a855ab040f765ec89dfe0eef",
|
|
395
395
|
"detectors/bun_interlocking_coverage/checks/interlocking_train_sequence.mjs": "8a8a8e88ce8a80024d0bdcc6866819fdfaa5a2ed26e8a9c5a459848d2de346d9",
|
|
396
|
-
"detectors/bun_interlocking_coverage/detect.mjs": "
|
|
396
|
+
"detectors/bun_interlocking_coverage/detect.mjs": "122b928bbb49affbf187c59cbf8e10d0190ca84cb5b98bc222bd2c1c1aac2f26",
|
|
397
397
|
"detectors/bun_interlocking_coverage/fixtures/clean/interlocking_production_runner/convex/trains/interlocking.ts": "e97288c4ca6084391bfa72d1457de26e99e9fa0c9540be4361e27731c19aeb6f",
|
|
398
398
|
"detectors/bun_interlocking_coverage/fixtures/clean/interlocking_production_runner/convex/trains/runner.ts": "33ac1f93e6c1b4d26827949159fff8481965e60db56c47d2c6ad3e462adef8c9",
|
|
399
399
|
"detectors/bun_interlocking_coverage/fixtures/clean/interlocking_production_runner/e2e/interlockings/match-resolution/routes.test.ts": "ba6ea85b3fbe15e3c49332da3ad2921a0ff3436a6fe3b5a5035fb35fdc874720",
|
|
@@ -493,7 +493,7 @@
|
|
|
493
493
|
"detectors/bun_interlocking_infrastructure/checks/journey_runner_boundary.mjs": "ad74ebb76d63ef648202ca31316647221e152f79bcba6aa2d30be4f0464ac10e",
|
|
494
494
|
"detectors/bun_interlocking_infrastructure/checks/journey_station_routing.mjs": "66c09cdc17b099a55fa0ca894bd85a44706742bdd29caa5347f10e6487b4e724",
|
|
495
495
|
"detectors/bun_interlocking_infrastructure/checks/wagon_contract_honoured.mjs": "79b5f824e7510f50e4925a98c01ef263290025748f64a27a11555f608d8001dc",
|
|
496
|
-
"detectors/bun_interlocking_infrastructure/detect.mjs": "
|
|
496
|
+
"detectors/bun_interlocking_infrastructure/detect.mjs": "6494579ec7b9d4680099401346337d73f4a52368ffb6b9d3b0fbca5dce2cde15",
|
|
497
497
|
"detectors/bun_interlocking_infrastructure/fixtures/clean/interlocking_delegates/server.ts": "36913357fdd3c5e375829a0554c605d70f5c05e2e83349f47505741598f6eb15",
|
|
498
498
|
"detectors/bun_interlocking_infrastructure/fixtures/clean/interlocking_delegates/src/match/wagon.ts": "ea202fa15fdf9d1391b1ae23343c9d1b09fcf8ef14f1dccfb8114ffaedea97c1",
|
|
499
499
|
"detectors/bun_interlocking_infrastructure/fixtures/clean/interlocking_delegates/src/trains/interlocking.ts": "d3872e912893e28e38e839ad4c8c15ed8381ff0b3db7015dd26df08bae88d395",
|
|
@@ -569,7 +569,7 @@
|
|
|
569
569
|
"detectors/bun_responsive_detector/checks/responsive_breakpoints_declared.mjs": "838fbb3b2b212d1ade6079667c8f31cae6e5a22843617bd044f3b5d0a3917ebb",
|
|
570
570
|
"detectors/bun_responsive_detector/checks/responsive_no_fixed_width.mjs": "6f607faeadf7cf8adba03faa3febb3dc2e7c8118d7e88367f1bc34ea533c692b",
|
|
571
571
|
"detectors/bun_responsive_detector/checks/responsive_viewport_meta.mjs": "496ba6f431586e94ebd9d278d1ea221f95e42a755d040e66247650c46a501cef",
|
|
572
|
-
"detectors/bun_responsive_detector/detect.mjs": "
|
|
572
|
+
"detectors/bun_responsive_detector/detect.mjs": "f12cd9889ceaba5656187aa6d9ee126f03a515a0b260ef120dec580249fe9e53",
|
|
573
573
|
"detectors/bun_responsive_detector/fixtures/clean/public/index.html": "9f3767fa3f022c9f6fccf80a5d53bcfe1ad305be353e55f043284f0e2cc72768",
|
|
574
574
|
"detectors/bun_responsive_detector/fixtures/clean/src/app.css": "281a22cd7284f077d66935bc2fd38b23aaefd9519d6a2b7c750884a1ec13a722",
|
|
575
575
|
"detectors/bun_responsive_detector/fixtures/clean/src/document.ts": "ffb04c4c21ed4f5bce23c22a6e745f0b63ea8602a7d769d361d687edad6d164a",
|
|
@@ -595,7 +595,7 @@
|
|
|
595
595
|
"detectors/bun_security_hygiene_detector/checks/sec_hardcoded_secret.mjs": "945d29152344d0ecc47c12d3f6e827ca1cd8bb272c3860d1865f4ca3bbd54850",
|
|
596
596
|
"detectors/bun_security_hygiene_detector/checks/sec_missing_auth.mjs": "a96df39709e5e8d9540f644e5f8f961b40b9e932f4b558479d3bbe785942e0c0",
|
|
597
597
|
"detectors/bun_security_hygiene_detector/checks/sec_sql_injection.mjs": "1f4d453c7bb497742c05bb3c31f0817e9d13b9c52890825777deb0c5740a5067",
|
|
598
|
-
"detectors/bun_security_hygiene_detector/detect.mjs": "
|
|
598
|
+
"detectors/bun_security_hygiene_detector/detect.mjs": "068919fe26f52f92d57b54e8c9298ddaf25e2f29e2b321a7d11483dd8f891e39",
|
|
599
599
|
"detectors/bun_security_hygiene_detector/fixtures/clean/server.ts": "d286c4bdcbede3ed24d038ba06aa2efbbc00c46e3bae92f4a37403de549a4e4c",
|
|
600
600
|
"detectors/bun_security_hygiene_detector/fixtures/dirty/db.ts": "980f39ace28a5b19c2a7a76abe0b64696b6f10a895f5c59a319e6d055134f1c4",
|
|
601
601
|
"detectors/bun_security_hygiene_detector/fixtures/dirty/errors.ts": "98b374298389e4c245920c4bc3a88ed4f24d73ca5db2a7777620f11a2395f107",
|
|
@@ -609,7 +609,7 @@
|
|
|
609
609
|
"detectors/bun_telemetry_code/checks/t_raw_string_emit.mjs": "6532e22a362d9f990b1e3444c65118b554a616eb4cdcb97132f2b9f3ae0867d9",
|
|
610
610
|
"detectors/bun_telemetry_code/checks/t_source_binding.mjs": "917809194779f60c7e4a0c8a58bc6b2eca39540aa331dfb82cd0c2ab530cf792",
|
|
611
611
|
"detectors/bun_telemetry_code/checks/t_vendor_sdk.mjs": "41efc80ac2e6c8aefcf22a0ed7c020836193f1f909c51885a998f73af35fa0a3",
|
|
612
|
-
"detectors/bun_telemetry_code/detect.mjs": "
|
|
612
|
+
"detectors/bun_telemetry_code/detect.mjs": "0d658d096f540bad55d5c40687cb4fe4a0817d7d5a94ca5a408ff51693e53486",
|
|
613
613
|
"detectors/bun_telemetry_code/fixtures/clean/plan/commons/E001.yaml": "f7f28a3eceb175ed53e32da5c98e3bea98ac7b892a487406ede0e48d699fa3e3",
|
|
614
614
|
"detectors/bun_telemetry_code/fixtures/clean/plan/commons/E002.yaml": "fcd06986619212291e88d6d68954ef77d50e5b6870728b6e8040bb160007112f",
|
|
615
615
|
"detectors/bun_telemetry_code/fixtures/clean/plan/commons/_commons.yaml": "2d047360373c4faec6efb9a1c14222478d65fdc5de8af16a38ad04fd3d854a04",
|
|
@@ -633,7 +633,7 @@
|
|
|
633
633
|
"detectors/bun_telemetry_test/checks/t_required_item_coverage.mjs": "975d229aedfad2af1002c6e314d480c7becd9e21bc5dad240cca848ea5dbe9ee",
|
|
634
634
|
"detectors/bun_telemetry_test/checks/t_test_binding.mjs": "401a8050568c8012a1a3a202180f2fa9ed57aac6e9147aa3852ce167a7238bdf",
|
|
635
635
|
"detectors/bun_telemetry_test/checks/t_timing_semantics.mjs": "80a29900674eb911261189e0318454aeec7535be199293c869cd760d3afc72f1",
|
|
636
|
-
"detectors/bun_telemetry_test/detect.mjs": "
|
|
636
|
+
"detectors/bun_telemetry_test/detect.mjs": "fd7631ff47d4078b3f5a7cea1fa15ff6765b35ab0170c493f5ffcca1f3193fd9",
|
|
637
637
|
"detectors/bun_telemetry_test/fixtures/clean/plan/commons/E001.yaml": "f7f28a3eceb175ed53e32da5c98e3bea98ac7b892a487406ede0e48d699fa3e3",
|
|
638
638
|
"detectors/bun_telemetry_test/fixtures/clean/plan/commons/E002.yaml": "fcd06986619212291e88d6d68954ef77d50e5b6870728b6e8040bb160007112f",
|
|
639
639
|
"detectors/bun_telemetry_test/fixtures/clean/plan/commons/_commons.yaml": "2d047360373c4faec6efb9a1c14222478d65fdc5de8af16a38ad04fd3d854a04",
|
|
@@ -669,7 +669,7 @@
|
|
|
669
669
|
"detectors/bun_tester_discipline_detector/checks/t_test_no_self_skip.mjs": "ac7deb2492f8aa0b9eb650128fdd21fcce359de5c88218eaf36f8fa58f74909f",
|
|
670
670
|
"detectors/bun_tester_discipline_detector/checks/t_test_phase_declared.mjs": "dc742cf8ac1296e4ea2d46544b843381a41d06d7efd66a2f12ada367404c7958",
|
|
671
671
|
"detectors/bun_tester_discipline_detector/checks/t_urn_identity.mjs": "7b7e41e80abefbdb95c91c1feca1638152ff7dee128a3cfc41ce5b163024019e",
|
|
672
|
-
"detectors/bun_tester_discipline_detector/detect.mjs": "
|
|
672
|
+
"detectors/bun_tester_discipline_detector/detect.mjs": "08475706598cbf20851e86eaab3d85eaee17273382ff6a569e787db237c2a0df",
|
|
673
673
|
"detectors/bun_tester_discipline_detector/fixtures/clean/audit.sec.test.ts": "36894354794c6d41ed2c8b8b9ceaed40f75b0849274c84c81b2e7dd6caf83be5",
|
|
674
674
|
"detectors/bun_tester_discipline_detector/fixtures/clean/checkout.red.test.ts": "35ca79c2bbfab61d9459b3d3177d97c18bea4d8e7777dcc92cae9970bb5c0827",
|
|
675
675
|
"detectors/bun_tester_discipline_detector/fixtures/clean/emit.telemetry.test.ts": "01fd00a8504c806561091e602b974b63f2e6e1d86abadb9fd9996ed869be3fda",
|
|
@@ -721,7 +721,7 @@
|
|
|
721
721
|
"detectors/bun_ts_metrics_detector/checks/ts_duplication.mjs": "12b5087c34741ce3fde573059d1afbaafc80ce1bfe8a235780113fd558dbbc7d",
|
|
722
722
|
"detectors/bun_ts_metrics_detector/checks/ts_quality_comments.mjs": "872d71d2165eba4cb39c975b09365cf67a64f1db5c55c0df9e86ff411e02ea31",
|
|
723
723
|
"detectors/bun_ts_metrics_detector/checks/ts_quality_mi.mjs": "69765d88441e98f4f38b7da0a416b7dab8b7f0072e562ea9d40d399802452067",
|
|
724
|
-
"detectors/bun_ts_metrics_detector/detect.mjs": "
|
|
724
|
+
"detectors/bun_ts_metrics_detector/detect.mjs": "a3eef9ad7b18a5743e508f5ac8c54cdf601cead679ed832629bfd4936d2ce6df",
|
|
725
725
|
"detectors/bun_ts_metrics_detector/fixtures/clean/domain/label.ts": "51e6fce80de70c168c750a2a71d93cde98a4a7fe2f29b4ff593ea2a531e1611a",
|
|
726
726
|
"detectors/bun_ts_metrics_detector/fixtures/clean/domain/offset.ts": "04b765ce74910a128e02c2a08676fd5b673cb952f2b8e2ee32fa5502a8ecb4a8",
|
|
727
727
|
"detectors/bun_ts_metrics_detector/fixtures/clean/domain/scale.ts": "fba087fb7b9a87a450f42a7d22119c8180b2093d25f819029f3004c815ce0863",
|
|
@@ -759,7 +759,7 @@
|
|
|
759
759
|
"detectors/htmx_e2e_detector/checks/responsive_journey_coverage.mjs": "dfa789719457cae7bfc16517f340d0e08d2a851219b70058f697eb0398019579",
|
|
760
760
|
"detectors/htmx_e2e_detector/checks/train_e2e_coverage.mjs": "6b99a8687357a9ccd7d45ed6913d5120ade36ebac7d2aedebd7d1d603b82b40a",
|
|
761
761
|
"detectors/htmx_e2e_detector/checks/visual_harness.mjs": "c59d8aeb3f9dd1ee841ce14000445a46a7d52007e29b5b6fca276e9394721f9f",
|
|
762
|
-
"detectors/htmx_e2e_detector/detect.mjs": "
|
|
762
|
+
"detectors/htmx_e2e_detector/detect.mjs": "ce1f6e77de229f7618e9f3ed49f7db3e019e2a533f3aa2b380bf2f8d2939f0fa",
|
|
763
763
|
"detectors/htmx_e2e_detector/fixtures/clean/e2e/buy-alias.a11y.e2e.ts": "40fdffb183946f5bcb753ad3368b5236f4a851df16f637f6ad3cfa09bf180559",
|
|
764
764
|
"detectors/htmx_e2e_detector/fixtures/clean/e2e/buy-inline.responsive.e2e.ts": "53fade584bb8fd1332149e0226e90191462af000ff8e8b7fe7fbcbe511d37bc7",
|
|
765
765
|
"detectors/htmx_e2e_detector/fixtures/clean/e2e/buy.a11y.e2e.ts": "4d5700c1d969d62bf3bd6e65887b202c79144ac23d1d1312fe06c546c70ea8c4",
|
|
@@ -818,7 +818,7 @@
|
|
|
818
818
|
"detectors/htmx_hypermedia_detector/checks/htmx_verb_endpoint_is_routed.mjs": "c61768ba4a4e9148623c0875c471cb92ffc9d1eb95f199263be019badc7ea7a5",
|
|
819
819
|
"detectors/htmx_hypermedia_detector/checks/htmx_verb_endpoint_same_origin.mjs": "1f3b1032f42cb8593d55619aeb74d35188d45d1cfb97ea533919a785051ba48c",
|
|
820
820
|
"detectors/htmx_hypermedia_detector/checks/htmx_verb_mutation_signals_progress.mjs": "41f143075d58feba071de04d690590bbc1be5a316b3b55e95a4a3d84e10cce23",
|
|
821
|
-
"detectors/htmx_hypermedia_detector/detect.mjs": "
|
|
821
|
+
"detectors/htmx_hypermedia_detector/detect.mjs": "b0e97c87c9e5c7fe236e2627f5692db926e435e9c658f66b7b547148247bf2f8",
|
|
822
822
|
"detectors/htmx_hypermedia_detector/fixtures/clean/htmx_fragment_escapes_interpolation/render.ts": "2c336b86a62fde5059eeca34251d62f37b51d6e4de59d5035f8adb6cb3f592c1",
|
|
823
823
|
"detectors/htmx_hypermedia_detector/fixtures/clean/htmx_swap_no_inline_handler/row.html": "ce357743cf217c14e49a5f74903a27a6abd95296390b38c66068dd8950662e97",
|
|
824
824
|
"detectors/htmx_hypermedia_detector/fixtures/clean/htmx_swap_oob_carries_id/fragment.html": "150417331b8f5885b3d2450e1df06190a93c20f811b27b222119623b253ff583",
|
|
@@ -840,7 +840,7 @@
|
|
|
840
840
|
"detectors/htmx_tester_detector/checks/t_fragment_asserts_returned_markup.mjs": "7e1b739ebb210235af7653709c6d0c41be67ac36a66615f9be25744f7c828a99",
|
|
841
841
|
"detectors/htmx_tester_detector/checks/t_swap_oob_asserts_destination_id.mjs": "680099f26550104a352563dcd3a0fe13232fe69d10a73ce20ed5e77619d789a4",
|
|
842
842
|
"detectors/htmx_tester_detector/checks/t_verb_endpoint_coverage.mjs": "02adf7785fe58b75c6a7accf2777e5345767eb4fd1cda343c5e7f02df0528069",
|
|
843
|
-
"detectors/htmx_tester_detector/detect.mjs": "
|
|
843
|
+
"detectors/htmx_tester_detector/detect.mjs": "48fe94f3e15e0d3fd4aa79f35ca6b0308561d1b8d3e06a5da37596f169633b1c",
|
|
844
844
|
"detectors/htmx_tester_detector/fixtures/clean/orders.test.ts": "9ab73cc026b69fd22ab553bc1f3fcba8e2035ba9c2c04397f47750fed7168e1b",
|
|
845
845
|
"detectors/htmx_tester_detector/fixtures/clean/panel.html": "9a5e34e4f2bdd2e99940f62afee61ed876747a3440cd916c9046294b2bf72e5d",
|
|
846
846
|
"detectors/htmx_tester_detector/fixtures/dirty/orders.test.ts": "b1d58b1b7f21c03aa8cb70a76dde74c551f6d9b6a4b6e3465e440d84b5a24281",
|
|
@@ -1257,8 +1257,8 @@
|
|
|
1257
1257
|
"planner-schemas/wmbt.schema.json": "7a3a5693bfcf01340667c2be4a3c48e74f34b1af7e8dc13372c0de06b7f4fe12",
|
|
1258
1258
|
"relationships.yaml": "5860a308ebc3ee7fa8172fc2c6633984000ab3003f0ae4b6fa28db48879eda22",
|
|
1259
1259
|
"src/agent.ts": "6d6c6e75908af8fbab13432f0001b0374bb25cf3dee46ba218dfd67e0090cb56",
|
|
1260
|
-
"src/ci.ts": "
|
|
1261
|
-
"src/cli.ts": "
|
|
1260
|
+
"src/ci.ts": "c4bc0a92e30da3db384e5bc968c45dae7b9de567dcee0e6493eb45cbd8f85652",
|
|
1261
|
+
"src/cli.ts": "995e41b3cb44c04f65f4d599f0fc51b93b17b7558b7c7dcfabed64de3d455250",
|
|
1262
1262
|
"src/docs-capability.ts": "bdeeb414649049b1cd4fa8008cada3a576318be51c43bec91bfa46a8e250c270",
|
|
1263
1263
|
"src/enforce.ts": "7e6b3a1fc7c90f8e1836ab3e4655778fb569a63be5e7c199de44024fc003e6be",
|
|
1264
1264
|
"src/hooks.ts": "6b579c030bb4772f08806e802f4f814444b1878bbac0d6c62bc10b4ee184e449",
|
|
@@ -1279,6 +1279,6 @@
|
|
|
1279
1279
|
"templates/agents/atdd-bun.integrity.test.ts": "dec6f6e5f65a08d9512fc703b367c163f8c9da1f6aa7fd466835c1ec30348a41",
|
|
1280
1280
|
"templates/docs/site.css": "482b3427e3a3cb02a85dc85cfbeac80592dfd53abf42fc92d6ea7071f22afc95",
|
|
1281
1281
|
"templates/github/atdd-bun-release.yml": "d9547e9e6ef3ae010d53d55314f6a54567f88bd900f7e50d994cd308601d2684",
|
|
1282
|
-
"templates/github/atdd-bun.yml": "
|
|
1282
|
+
"templates/github/atdd-bun.yml": "e67121bc42481906ceb298dd87c9ec70bce55dd59b31a79c1010e53053eec272"
|
|
1283
1283
|
}
|
|
1284
1284
|
}
|
package/package.json
CHANGED
package/src/ci.ts
CHANGED
|
@@ -10,7 +10,13 @@ const version = (await Bun.file(join(root, "package.json")).json() as { version:
|
|
|
10
10
|
* whose base branch is not main or master is covered too. The integrity check compares against this same rendering.
|
|
11
11
|
* Each branch is written as a JSON string, a YAML scalar a branch name can never break out of. */
|
|
12
12
|
export async function renderWorkflow(repo = process.cwd()) {
|
|
13
|
-
|
|
13
|
+
const configPath = join(repo, "atdd-bun.yaml");
|
|
14
|
+
let rejectNew = false;
|
|
15
|
+
if (existsSync(configPath)) try {
|
|
16
|
+
const config = Bun.YAML.parse(await readFile(configPath, "utf8"));
|
|
17
|
+
rejectNew = Boolean(config && typeof config === "object" && !Array.isArray(config) && (config as { ratchet?: { mode?: unknown } }).ratchet?.mode === "reject-new");
|
|
18
|
+
} catch { /* policy(repo) below gives its existing parse diagnostic */ }
|
|
19
|
+
return (await readFile(template, "utf8")).replace("{{VERSION}}", version).replace("{{PROTECTED_BRANCHES}}", (await policy(repo)).protected_branches.map(branch => JSON.stringify(branch)).join(", ")).replace("{{ENFORCEMENT}}", rejectNew ? 'bun run atdd-bun all --ratchet --base "$ATDD_BASE_REF" --ratchet-activate-profiles' : "bun run atdd-bun all");
|
|
14
20
|
}
|
|
15
21
|
const githubPackagesRegistry = /^\s*@[\w.-]+:registry\s*=\s*https:\/\/npm\.pkg\.github\.com\/?\s*$/im;
|
|
16
22
|
const githubPackagesAuth = /^\s*\/\/npm\.pkg\.github\.com\/:_authToken\s*=\s*(.*?)\s*$/gim;
|
package/src/cli.ts
CHANGED
|
@@ -170,7 +170,7 @@ if (!args.includes("--ratchet")) {
|
|
|
170
170
|
else {
|
|
171
171
|
const baseConfig = await configAt(scratch), baseProfiles = profileActivation ? await enabledProfiles(scratch) : normalizedRequested.includes("all") ? await enabledProfiles(scratch) : normalizedRequested;
|
|
172
172
|
const ordinaryContextMatches = stable(baseProfiles).join(",") === stable(candidateProfiles).join(",") && contextDigest(baseConfig, baseProfiles) === contextDigest(candidateConfig, candidateProfiles);
|
|
173
|
-
const activationIsValid = isStrictProfileExpansion(baseProfiles, candidateProfiles) && activationContextDigest(baseConfig) === activationContextDigest(candidateConfig);
|
|
173
|
+
const activationIsValid = ordinaryContextMatches || (isStrictProfileExpansion(baseProfiles, candidateProfiles) && activationContextDigest(baseConfig) === activationContextDigest(candidateConfig));
|
|
174
174
|
if (!(profileActivation ? activationIsValid : ordinaryContextMatches)) { console.error(profileActivation ? "ratchet profile activation requires an explicit monotonic profile expansion and identical non-profile context" : "ratchet base and candidate profile/context differ; use a separately governed adoption path"); process.exitCode = 1; }
|
|
175
175
|
else {
|
|
176
176
|
const [baseFindings, candidateFindings] = await Promise.all([enforce({ root: scratch, profiles: candidateProfiles as Profile[] }), enforce({ root: candidateRoot, profiles: candidateProfiles as Profile[] })]);
|
|
@@ -15,10 +15,9 @@ jobs:
|
|
|
15
15
|
name: atdd-bun
|
|
16
16
|
runs-on: ubuntu-latest
|
|
17
17
|
env:
|
|
18
|
-
# The policy
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
ATDD_BASE_REF: ${{ github.event_name == 'push' && github.event.before || github.event_name == 'merge_group' && github.event.merge_group.base_sha || '' }}
|
|
18
|
+
# The immutable policy/ratchet base: the PR target object (not its mutable branch name), the pre-push tip, or the
|
|
19
|
+
# merge-queue target. Reject-new refuses absent, zero, unresolved, or non-ancestor bases.
|
|
20
|
+
ATDD_BASE_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event_name == 'push' && github.event.before || github.event_name == 'merge_group' && github.event.merge_group.base_sha || '' }}
|
|
22
21
|
steps:
|
|
23
22
|
- uses: actions/checkout@v4
|
|
24
23
|
with:
|
|
@@ -31,7 +30,7 @@ jobs:
|
|
|
31
30
|
env:
|
|
32
31
|
NODE_AUTH_TOKEN: ${{ github.token }}
|
|
33
32
|
- run: bun run atdd-bun integrity
|
|
34
|
-
- run:
|
|
33
|
+
- run: {{ENFORCEMENT}}
|
|
35
34
|
- run: bun test
|
|
36
35
|
- run: bun run atdd-bun release check
|
|
37
36
|
- uses: actions/upload-artifact@v4
|