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 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
@@ -40,6 +40,10 @@ bastard status
40
40
  bastard run
41
41
  ```
42
42
 
43
+ ## Example Project
44
+
45
+ See [`examples/todo-app/`](examples/todo-app/) — a minimal todo app that went through all 8 rounds. The code is < 200 LOC. The documents are the star.
46
+
43
47
  ## The Pipeline
44
48
 
45
49
  ```
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.0.0");
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
- program.command("slop [path]").description("Scan for AI slop patterns \u2014 works on ANY project (default: src/ or cwd)").action((pathArg) => {
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
- displaySlopReport(report);
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
- displayDesignScore(report);
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
- displayAudit(slop, design);
3135
- if (slop.matches.length > 0) {
3136
- displaySlopReport(slop);
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 (design.violations.length > 0) {
3139
- displayDesignScore(design);
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(` [![Shipped with BASTARD](${url})](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();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bastard-framework",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Build Any SaaS Through Agent Roles & Discipline — The guardrails between your favorite Claude Code frameworks.",
5
5
  "type": "module",
6
6
  "bin": {