bastard-framework 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +4 -0
- package/dist/cli.js +66 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ All notable changes to BASTARD will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [1.1.0] - 2026-04-03
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `--json` flag on `slop`, `score`, `audit` commands for machine-readable output
|
|
12
|
+
- `--fail-below <grade>` flag on `slop`, `score`, `audit` for CI enforcement (exit 1 if below threshold)
|
|
13
|
+
- `bastard badge [path]` command — generates shields.io badge with Slop + Design scores
|
|
14
|
+
- GitHub Action (`action/action.yml`) — run BASTARD audit in CI, post PR comments, fail checks
|
|
15
|
+
- Example project: `examples/todo-app/` — complete 8-round reference with all pipeline artifacts
|
|
16
|
+
|
|
8
17
|
## [1.0.0] - 2026-04-02
|
|
9
18
|
|
|
10
19
|
### Added
|
package/README.md
CHANGED
package/dist/cli.js
CHANGED
|
@@ -2791,7 +2791,7 @@ function displayAudit(slop, design) {
|
|
|
2791
2791
|
|
|
2792
2792
|
// src/cli.ts
|
|
2793
2793
|
var program = new Command();
|
|
2794
|
-
program.name("bastard").description("Build Any SaaS Through Agent Roles & Discipline").version("1.
|
|
2794
|
+
program.name("bastard").description("Build Any SaaS Through Agent Roles & Discipline").version("1.1.0");
|
|
2795
2795
|
program.command("init [name]").description("Initialize a new BASTARD project").option("--install-parents", "Also install all parent frameworks").option("--with-hooks", "Also install Claude Code guard hooks").action(async (name, opts) => {
|
|
2796
2796
|
const projectRoot = process.cwd();
|
|
2797
2797
|
if (stateExists(projectRoot)) {
|
|
@@ -3117,26 +3117,81 @@ function resolveAuditTarget(pathArg) {
|
|
|
3117
3117
|
const srcDir = resolve3(cwd, "src");
|
|
3118
3118
|
return existsSync10(srcDir) ? srcDir : cwd;
|
|
3119
3119
|
}
|
|
3120
|
-
|
|
3120
|
+
var GRADE_ORDER = { "A": 1, "B": 2, "C": 3, "D": 4, "F": 5, "-": 0 };
|
|
3121
|
+
function isScoreBelow(score, threshold) {
|
|
3122
|
+
return (GRADE_ORDER[score] ?? 5) > (GRADE_ORDER[threshold] ?? 5);
|
|
3123
|
+
}
|
|
3124
|
+
program.command("slop [path]").description("Scan for AI slop patterns \u2014 works on ANY project (default: src/ or cwd)").option("--json", "Output as JSON").option("--fail-below <grade>", "Exit 1 if score is below this grade (A-F)").action((pathArg, opts) => {
|
|
3121
3125
|
const targetDir = resolveAuditTarget(pathArg);
|
|
3122
3126
|
const report = runSlopScan(targetDir);
|
|
3123
|
-
|
|
3127
|
+
if (opts.json) {
|
|
3128
|
+
console.log(JSON.stringify(report, null, 2));
|
|
3129
|
+
} else {
|
|
3130
|
+
displaySlopReport(report);
|
|
3131
|
+
}
|
|
3132
|
+
if (opts.failBelow && isScoreBelow(report.score, opts.failBelow)) {
|
|
3133
|
+
process.exit(1);
|
|
3134
|
+
}
|
|
3124
3135
|
});
|
|
3125
|
-
program.command("score [path]").description("Check design token compliance \u2014 works on ANY project").action((pathArg) => {
|
|
3136
|
+
program.command("score [path]").description("Check design token compliance \u2014 works on ANY project").option("--json", "Output as JSON").option("--fail-below <grade>", "Exit 1 if score is below this grade (A-F)").action((pathArg, opts) => {
|
|
3126
3137
|
const targetDir = resolveAuditTarget(pathArg);
|
|
3127
3138
|
const report = runDesignScore(targetDir, targetDir);
|
|
3128
|
-
|
|
3139
|
+
if (opts.json) {
|
|
3140
|
+
console.log(JSON.stringify(report, null, 2));
|
|
3141
|
+
} else {
|
|
3142
|
+
displayDesignScore(report);
|
|
3143
|
+
}
|
|
3144
|
+
if (opts.failBelow && isScoreBelow(report.score, opts.failBelow)) {
|
|
3145
|
+
process.exit(1);
|
|
3146
|
+
}
|
|
3129
3147
|
});
|
|
3130
|
-
program.command("audit [path]").description("AI Slop + Design Score audit \u2014 works on ANY project, no init needed").action((pathArg) => {
|
|
3148
|
+
program.command("audit [path]").description("AI Slop + Design Score audit \u2014 works on ANY project, no init needed").option("--json", "Output as JSON").option("--fail-below <grade>", "Exit 1 if slop score is below this grade (A-F)").action((pathArg, opts) => {
|
|
3131
3149
|
const targetDir = resolveAuditTarget(pathArg);
|
|
3132
3150
|
const slop = runSlopScan(targetDir);
|
|
3133
3151
|
const design = runDesignScore(targetDir, targetDir);
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3152
|
+
if (opts.json) {
|
|
3153
|
+
console.log(JSON.stringify({ slop, design }, null, 2));
|
|
3154
|
+
} else {
|
|
3155
|
+
displayAudit(slop, design);
|
|
3156
|
+
if (slop.matches.length > 0) {
|
|
3157
|
+
displaySlopReport(slop);
|
|
3158
|
+
}
|
|
3159
|
+
if (design.violations.length > 0) {
|
|
3160
|
+
displayDesignScore(design);
|
|
3161
|
+
}
|
|
3137
3162
|
}
|
|
3138
|
-
if (
|
|
3139
|
-
|
|
3163
|
+
if (opts.failBelow && isScoreBelow(slop.score, opts.failBelow)) {
|
|
3164
|
+
process.exit(1);
|
|
3140
3165
|
}
|
|
3141
3166
|
});
|
|
3167
|
+
program.command("badge [path]").description('Generate a "Shipped with BASTARD" badge for your README').action((pathArg) => {
|
|
3168
|
+
const targetDir = resolveAuditTarget(pathArg);
|
|
3169
|
+
const slop = runSlopScan(targetDir);
|
|
3170
|
+
const design = runDesignScore(targetDir, targetDir);
|
|
3171
|
+
const slopScore = slop.score;
|
|
3172
|
+
const designScore = design.score === "-" ? "N/A" : design.score;
|
|
3173
|
+
const colorMap = {
|
|
3174
|
+
"A": "brightgreen",
|
|
3175
|
+
"B": "green",
|
|
3176
|
+
"C": "yellow",
|
|
3177
|
+
"D": "orange",
|
|
3178
|
+
"F": "red",
|
|
3179
|
+
"-": "lightgrey",
|
|
3180
|
+
"N/A": "lightgrey"
|
|
3181
|
+
};
|
|
3182
|
+
const worstScore = isScoreBelow(slopScore, designScore === "N/A" ? "A" : designScore) ? slopScore : designScore === "N/A" ? slopScore : designScore;
|
|
3183
|
+
const color = colorMap[worstScore] ?? "lightgrey";
|
|
3184
|
+
const label = encodeURIComponent("BASTARD");
|
|
3185
|
+
const message = encodeURIComponent(`Slop: ${slopScore} | Design: ${designScore}`);
|
|
3186
|
+
const url = `https://img.shields.io/badge/${label}-${message}-${color}?style=flat-square`;
|
|
3187
|
+
console.log(chalk2.bold("\n Shipped with BASTARD\n"));
|
|
3188
|
+
console.log(` Slop Score: ${slopScore}`);
|
|
3189
|
+
console.log(` Design Score: ${designScore}`);
|
|
3190
|
+
console.log(chalk2.bold("\n Markdown:\n"));
|
|
3191
|
+
console.log(` [](https://github.com/Denis-hamon/bastard)
|
|
3192
|
+
`);
|
|
3193
|
+
console.log(chalk2.bold(" HTML:\n"));
|
|
3194
|
+
console.log(` <a href="https://github.com/Denis-hamon/bastard"><img src="${url}" alt="Shipped with BASTARD"></a>
|
|
3195
|
+
`);
|
|
3196
|
+
});
|
|
3142
3197
|
program.parse();
|