anti-slop-engineering 1.2.1 → 1.4.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/.skills.json +1 -1
- package/README.md +57 -4
- package/SKILL.md +6 -1
- package/bin/cli.js +24 -3
- package/dist/bin/anti-slop-rust +0 -0
- package/dist/bin/toil-guard +0 -0
- package/install.sh +8 -2
- package/marketplace.json +1 -1
- package/package.json +3 -1
- package/references/anti-pattern-catalog.md +1 -0
- package/scripts/bump_version.py +276 -0
- package/scripts/future_scale_guard.py +197 -0
- package/scripts/paranoid_guard.py +201 -0
- package/services/anti-slop-rust/Cargo.lock +1 -1
- package/services/anti-slop-rust/Cargo.toml +1 -1
- package/services/toil-guard-go/pkg/model/types.go +1 -1
- package/services/toil-guard-go/pkg/server/server.go +1 -1
- package/skills/future-scale-gate/SKILL.md +101 -0
- package/skills/future-scale-gate/evals/scenarios.json +78 -0
- package/skills/future-scale-gate/examples/runtime-envelope-record.json +61 -0
- package/skills/future-scale-gate/references/foundation-method.md +73 -0
- package/skills/future-scale-gate/references/record-contract.md +47 -0
- package/skills/future-scale-gate/usecases/architect.md +13 -0
- package/skills/future-scale-gate/usecases/review.md +10 -0
- package/skills/paranoid-principal-architect/Playbook/paranoid_principal_architect_playbook.md +92 -0
- package/skills/paranoid-principal-architect/SKILL.md +140 -0
- package/skills/paranoid-principal-architect/evals/scenarios.json +112 -0
- package/skills/paranoid-principal-architect/examples/hardened-idempotent-service.ts +177 -0
- package/skills/paranoid-principal-architect/examples/paranoid-architecture-record.json +58 -0
- package/skills/paranoid-principal-architect/references/modern-web-platform.md +134 -0
- package/skills/paranoid-principal-architect/references/scale-concurrency-patterns.md +173 -0
- package/skills/paranoid-principal-architect/references/threat-record-contract.md +130 -0
- package/skills/paranoid-principal-architect/references/zero-trust-security.md +128 -0
- package/skills/paranoid-principal-architect/usecases/architect.md +40 -0
- package/skills/paranoid-principal-architect/usecases/implement.md +28 -0
- package/skills/paranoid-principal-architect/usecases/review.md +51 -0
package/.skills.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://skills.sh/schema.json",
|
|
3
3
|
"name": "anti-slop-engineering",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.4.0",
|
|
5
5
|
"description": "An Engineering Discipline Playbook & Guard System for AI Coding Agents. Enforces Google SRE, Clean-Room Senior Dev Ladders, and Rust/Go Microservices.",
|
|
6
6
|
"repository": "https://github.com/imMamdouhaboammar/anti-slop-engineering",
|
|
7
7
|
"author": "Mamdouh Aboammar",
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
[](https://skills.sh)
|
|
13
13
|
[](https://claude.ai)
|
|
14
14
|
|
|
15
|
-
[Install](#install) · [What it catches](#what-it-catches) · [Engines](#engines) · [Decision Guard](#decision-guard) · [Root-Fix Gate](#root-fix-gate) · [Agent skill](#agent-skill) · [Anti-pattern catalog](#anti-pattern-catalog-
|
|
15
|
+
[Install](#install) · [What it catches](#what-it-catches) · [Engines](#engines) · [Decision Guard](#decision-guard) · [Root-Fix Gate](#root-fix-gate) · [Future-Scale Gate](#future-scale-gate) · [Paranoid Architect](#the-paranoid-principal-architect) · [Install Anti-Slop](#install-anti-slop-oxlint) · [Agent skill](#agent-skill) · [Anti-pattern catalog](#anti-pattern-catalog-217-patterns)
|
|
16
16
|
|
|
17
17
|
</div>
|
|
18
18
|
|
|
@@ -245,9 +245,62 @@ The JSON checker uses only Python standard library and Git when diff inspection
|
|
|
245
245
|
|
|
246
246
|
---
|
|
247
247
|
|
|
248
|
+
## Future-Scale Gate
|
|
249
|
+
|
|
250
|
+
The [Future-Scale Gate](skills/future-scale-gate/SKILL.md) protects long-lived systems against two opposite failures: locking a core contract to today's workload, and implementing expensive infrastructure for an unverified hypothetical future.
|
|
251
|
+
|
|
252
|
+
| Question | Required evidence |
|
|
253
|
+
| --- | --- |
|
|
254
|
+
| What changes over the product's lifetime? | Credible scenarios with sources, stress axes and failure consequences |
|
|
255
|
+
| Which foundation would be costly to change later? | Reversal cost, alternative designs and migration/exit path |
|
|
256
|
+
| What must be established now? | Small stable boundary and a representative evolution test |
|
|
257
|
+
| What should wait? | Deferred capacity with a concrete revisit trigger |
|
|
258
|
+
|
|
259
|
+
Examples include a simulation language keeping its semantics portable across runtimes, a versioned public data format, or a future tenant-isolation constraint. The Gate does not require microservices, Rust, distributed systems or a provider bundle by default.
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
node bin/cli.js future-scale audit skills/future-scale-gate/examples/runtime-envelope-record.json --json
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
The bundled example intentionally recommends `pause` because its alternate-engine experiment has not been run. The zero-dependency checker validates record completeness, not forecast accuracy or actual scalability. The ten semantic evaluation scenarios are proposed tests, not measured model effectiveness.
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## The Paranoid Principal Architect
|
|
270
|
+
|
|
271
|
+
The [Paranoid Principal Architect](skills/paranoid-principal-architect/SKILL.md) skill enforces an uncompromising, zero-trust engineering posture designed for day-one 10,000,000 concurrent user scale. It rejects optimistic "happy-path" code generation, unparsed inputs, unbounded async loops, hot-key lock contention, and client authority.
|
|
272
|
+
|
|
273
|
+
| Pillar | Strict Enforcement |
|
|
274
|
+
| --- | --- |
|
|
275
|
+
| **10M Concurrent Users Axiom** | Little's Law capacity budgeting, 16-shard counters, keyset cursor pagination (`LIMIT <= 100`), semaphore worker pools |
|
|
276
|
+
| **The Internet is a Battlefield** | Parse don't validate (Zod/Valibot `.strict()`), data-layer ownership checks in queries, constant-time `crypto.timingSafeEqual` |
|
|
277
|
+
| **Murphy's Law by Default** | Mandatory `Idempotency-Key` headers on mutations, `AbortSignal.timeout(ms)` on all outbound I/O, exponential backoff with full jitter |
|
|
278
|
+
| **Modern Web Standards** | Native platform primitives (`structuredClone`, Web Streams, `URLSearchParams`), native `<dialog>` modals, strict branded types |
|
|
279
|
+
|
|
280
|
+
Audit architectural threat records:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
bunx anti-slop-engineering paranoid audit skills/paranoid-principal-architect/examples/paranoid-architecture-record.json --json
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Install Anti-Slop (Oxlint)
|
|
289
|
+
|
|
290
|
+
For TypeScript and JavaScript projects, install the opinionated anti-slop Oxlint lint rules to catch runtime type assertion risks, unconstrained object parameters, and module mocking leaks at lint-time:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# In your target repository:
|
|
294
|
+
npx skills add imMamdouhaboammar/anti-slop-engineering
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Follow the procedure in [install-anti-slop](skills/install-anti-slop/SKILL.md) to register the bundled plugins (`anti-slop` and optional `anti-slop-effect`) directly into `oxlint.config.ts` or `.oxlintrc.json`.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
248
301
|
## Agent skill
|
|
249
302
|
|
|
250
|
-
The agent skill wires Anti-Slop Engineering into your AI coding agent's context. Once installed, code changes are guided by the Seven Gates, the
|
|
303
|
+
The agent skill wires Anti-Slop Engineering into your AI coding agent's context. Once installed, code changes are guided by the Seven Gates, the 217-pattern anti-pattern catalog, and the Google SRE enforcement rules.
|
|
251
304
|
|
|
252
305
|
**Supported environments:**
|
|
253
306
|
|
|
@@ -267,9 +320,9 @@ When installed via `npm install anti-slop-engineering` or `bun add anti-slop-eng
|
|
|
267
320
|
|
|
268
321
|
---
|
|
269
322
|
|
|
270
|
-
## Anti-pattern catalog (
|
|
323
|
+
## Anti-pattern catalog (217 patterns)
|
|
271
324
|
|
|
272
|
-
The catalog in [`references/anti-pattern-catalog.md`](references/anti-pattern-catalog.md) documents
|
|
325
|
+
The catalog in [`references/anti-pattern-catalog.md`](references/anti-pattern-catalog.md) documents 217 diagnostic patterns across 14 engineering domains, each with a canonical ID, symptom, root cause, and remediation.
|
|
273
326
|
|
|
274
327
|
**Domains covered:**
|
|
275
328
|
|
package/SKILL.md
CHANGED
|
@@ -4,7 +4,7 @@ description: Prevent, detect, and repair AI coding slop and dirty engineering in
|
|
|
4
4
|
author: Mamdouh Aboammar <mamdouhfces1997@gmail.com>
|
|
5
5
|
license: MIT
|
|
6
6
|
metadata:
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.4.0"
|
|
8
8
|
focus: "engineering-discipline"
|
|
9
9
|
repository: "https://github.com/imMamdouhaboammar/anti-slop-engineering"
|
|
10
10
|
---
|
|
@@ -39,6 +39,8 @@ metadata:
|
|
|
39
39
|
- **Practical DRY 3-Point Barrier:** Shared utilities or abstractions are permitted only when appearing in >=2 real existing call-sites, when all call-sites require identical modifications upon change, and when the abstraction can be named without coordinating conjunctions (`and`, `or`).
|
|
40
40
|
15. **Decision Guard before consequential commitments:** When the task proposes derived metrics, an architectural stack, infrastructure, persistence, or a difficult-to-reverse engineering decision, read [Decision Guard](skills/decision-guard/SKILL.md). Check direct evidence and independent alternatives before treating the proposed method as necessary. Never substitute the decision record's structural check for source verification.
|
|
41
41
|
16. **Root-Fix Gate for scattered symptom patches:** When a local behavior change spreads through controllers, views, endpoints or multiple layers, read [Root-Fix Gate](skills/root-fix-gate/SKILL.md). Trace the owner of the domain invariant, compare a coherent source correction with consumer workarounds, and inspect actual change paths. Do not assume the model owns every rule or that few files prove safety.
|
|
42
|
+
17. **Future-Scale Gate for irreversible foundations:** Before locking in a core runtime, public contract, persistence model, or platform boundary for a long-lived product, read [Future-Scale Gate](skills/future-scale-gate/SKILL.md). Establish credible future operating scenarios, assess reversal cost and run a bounded evolution proof. Design the cheap necessary foundation now; defer speculative infrastructure with measurable revisit triggers. Lack of a present bottleneck does not disprove future architectural constraints.
|
|
43
|
+
18. **Paranoid Principal Architect for 10M scale & zero-trust:** When designing system architectures, generating backend/frontend code, refactoring critical paths, conducting adversarial security reviews, or diagnosing scale bottlenecks, race conditions, memory leaks, and EDoS vulnerabilities, read [Paranoid Principal Architect](skills/paranoid-principal-architect/SKILL.md). Enforce the 10,000,000 Concurrent Users Axiom and Active Battlefield Zero-Trust mindset. Reject happy-path assumptions, unbounded async loops, hot keys, client authority, and unparsed inputs from line one.
|
|
42
44
|
|
|
43
45
|
## Activation / modes
|
|
44
46
|
|
|
@@ -51,6 +53,8 @@ Select the relevant mode and follow the same gates:
|
|
|
51
53
|
- **NOTED_SLOP:** codify newly observed AI slop into a diagnostic catalog pattern, agent directive, and automated diff guard heuristic (see [CONTRIBUTING.md](CONTRIBUTING.md)).
|
|
52
54
|
- **DECIDE:** when premises, direct answers or long-term architecture choices are materially uncertain, follow [Decision Guard](skills/decision-guard/SKILL.md) before BUILD. Return to ordinary modes after a decision; skip the extra protocol for routine repairs.
|
|
53
55
|
- **ROOT-FIX:** when a symptom attracts scattered fixes or ownership is uncertain, follow [Root-Fix Gate](skills/root-fix-gate/SKILL.md) to establish the change boundary, then resume BUILD/FIX with regression tests.
|
|
56
|
+
- **FUTURE-SCALE:** when an architecture commitment would be expensive to reverse as the product evolves, follow [Future-Scale Gate](skills/future-scale-gate/SKILL.md). Skip routine reversible edits and avoid capacity theater.
|
|
57
|
+
- **PARANOID-ARCHITECT:** when building or reviewing systems against 10M concurrent user load, adversarial traffic, race conditions, hot-key contention, or zero-trust boundaries, follow [Paranoid Principal Architect](skills/paranoid-principal-architect/SKILL.md).
|
|
54
58
|
|
|
55
59
|
For extensive audits, load [anti-pattern catalog](references/anti-pattern-catalog.md). For Google SRE discipline and distributed resilience patterns, load [google-sre-discipline](references/google-sre-discipline.md). For any test changes, load [test integrity policy](references/test-integrity.md). For a PR or merge request, load [PR review protocol](references/pr-review.md). For elevated permissions, sensitive code, network access, or deployment, load [security and execution boundaries](references/security-and-operations.md). For project-specific exceptions, load [judgment and exceptions](references/engineering-judgment.md). For community contributions, follow [contributor guidelines](CONTRIBUTING.md).
|
|
56
60
|
|
|
@@ -65,6 +69,7 @@ For extensive audits, load [anti-pattern catalog](references/anti-pattern-catalo
|
|
|
65
69
|
- Run an appropriate baseline build/test if feasible; label any existing failure as baseline, not caused by this change.
|
|
66
70
|
- For a derived-answer task, inspect existing direct sources before constructing proxies. For an architectural commitment, inspect the product's actual rendering, workload, operations and persistence needs instead of defaulting to a familiar provider bundle. Load `skills/decision-guard/SKILL.md` only when this uncertainty is material.
|
|
67
71
|
- For a proposed cross-layer patch, identify the first incorrect boundary and trace writes/reads before editing consumers. Load `skills/root-fix-gate/SKILL.md` when the same symptom would otherwise be patched in several places.
|
|
72
|
+
- For a foundational architectural commitment, classify credible future stresses and costly reversal points before using today's workload as an excuse to hard-wire the system. Load `skills/future-scale-gate/SKILL.md` only for consequential choices and verify an actual evolution path before claiming future readiness.
|
|
68
73
|
- For new projects, services, components, or SDK integrations, identify the official installer, CLI generator, and canonical starter boilerplate before writing code. Do not manually assemble configurations or directory trees from memory. Never generate unprompted documentation files, submission dossiers, or speculative third-party platform guides.
|
|
69
74
|
|
|
70
75
|
### Gate 1: Establish a change contract
|
package/bin/cli.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Copyright (c) 2026 Mamdouh Aboammar <mamdouhfces1997@gmail.com> and contributors
|
|
4
4
|
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
|
-
import { existsSync, mkdirSync } from "node:fs";
|
|
6
|
+
import { copyFileSync, existsSync, mkdirSync } from "node:fs";
|
|
7
7
|
import { basename, dirname, resolve } from "node:path";
|
|
8
8
|
import process from "node:process";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
@@ -15,6 +15,9 @@ const diffGuardScript = resolve(rootDir, "scripts", "diff_guard.py");
|
|
|
15
15
|
const sreGuardScript = resolve(rootDir, "scripts", "sre_guard.py");
|
|
16
16
|
const decisionGuardScript = resolve(rootDir, "scripts", "decision_guard.py");
|
|
17
17
|
const rootFixGuardScript = resolve(rootDir, "scripts", "root_fix_guard.py");
|
|
18
|
+
const futureScaleGuardScript = resolve(rootDir, "scripts", "future_scale_guard.py");
|
|
19
|
+
const paranoidGuardScript = resolve(rootDir, "scripts", "paranoid_guard.py");
|
|
20
|
+
const bumpVersionScript = resolve(rootDir, "scripts", "bump_version.py");
|
|
18
21
|
const nativeSuffix = process.platform === "win32" ? ".exe" : "";
|
|
19
22
|
const rustExecutable = "anti-slop-rust" + nativeSuffix;
|
|
20
23
|
const goExecutable = "toil-guard" + nativeSuffix;
|
|
@@ -33,7 +36,7 @@ if (executableAliases[invokedAs]) args.unshift(executableAliases[invokedAs]);
|
|
|
33
36
|
|
|
34
37
|
function printBanner() {
|
|
35
38
|
console.log(`
|
|
36
|
-
🛡️ Anti-Slop Engineering CLI (v1.
|
|
39
|
+
🛡️ Anti-Slop Engineering CLI (v1.4.0)
|
|
37
40
|
Clean-Room AI Coding Guard & High-Performance Polyglot Architecture
|
|
38
41
|
Engines: Standard Library Python Guard | Rust Microservice | Go Toil Guard
|
|
39
42
|
Author: Mamdouh Aboammar <mamdouhfces1997@gmail.com>
|
|
@@ -52,6 +55,9 @@ Commands:
|
|
|
52
55
|
sre, sre-guard Run Python Google SRE Guard (zero-dependency stdlib fallback)
|
|
53
56
|
decision audit <file> Check a Decision Guard JSON record for missing evidence and trade-offs
|
|
54
57
|
root-fix audit <file> Check root-cause ownership, change plan and optional Git diff
|
|
58
|
+
future-scale audit <file> Check future operating envelope, reversibility and evolution proof
|
|
59
|
+
paranoid audit <file> Check a Paranoid Architect record for zero-trust and 10M scale compliance
|
|
60
|
+
bump [part] Bump version across all 10 manifests (patch, minor, major, or explicit)
|
|
55
61
|
test Run unit test suite
|
|
56
62
|
contribute Print guidelines on reporting noted slop or opening PRs
|
|
57
63
|
|
|
@@ -172,7 +178,16 @@ function runBuild() {
|
|
|
172
178
|
console.error(`Go build failed with exit code ${goCode}`);
|
|
173
179
|
process.exit(goCode ?? 1);
|
|
174
180
|
}
|
|
175
|
-
|
|
181
|
+
mkdirSync(resolve(rootDir, "dist", "bin"), { recursive: true });
|
|
182
|
+
copyFileSync(
|
|
183
|
+
resolve(rootDir, "services", "anti-slop-rust", "target", "release", rustExecutable),
|
|
184
|
+
resolve(rootDir, "dist", "bin", rustExecutable)
|
|
185
|
+
);
|
|
186
|
+
copyFileSync(
|
|
187
|
+
resolve(rootDir, "services", "toil-guard-go", "bin", goExecutable),
|
|
188
|
+
resolve(rootDir, "dist", "bin", goExecutable)
|
|
189
|
+
);
|
|
190
|
+
console.log("All native microservices built successfully and staged in dist/bin/.");
|
|
176
191
|
process.exit(0);
|
|
177
192
|
});
|
|
178
193
|
});
|
|
@@ -200,6 +215,12 @@ if (cmd === "build") {
|
|
|
200
215
|
runPythonScript(decisionGuardScript, args.slice(1), "decision_guard");
|
|
201
216
|
} else if (cmd === "root-fix") {
|
|
202
217
|
runPythonScript(rootFixGuardScript, args.slice(1), "root_fix_guard");
|
|
218
|
+
} else if (cmd === "future-scale") {
|
|
219
|
+
runPythonScript(futureScaleGuardScript, args.slice(1), "future_scale_guard");
|
|
220
|
+
} else if (cmd === "paranoid") {
|
|
221
|
+
runPythonScript(paranoidGuardScript, args.slice(1), "paranoid_guard");
|
|
222
|
+
} else if (cmd === "bump") {
|
|
223
|
+
runPythonScript(bumpVersionScript, args.slice(1), "bump_version");
|
|
203
224
|
} else if (args.includes("--help") || args.includes("-h")) {
|
|
204
225
|
printBanner();
|
|
205
226
|
process.exit(0);
|
|
Binary file
|
|
Binary file
|
package/install.sh
CHANGED
|
@@ -35,18 +35,24 @@ install_to() {
|
|
|
35
35
|
mkdir -p "$(dirname "$dest")"
|
|
36
36
|
rm -rf "$dest"
|
|
37
37
|
mkdir -p "$dest"
|
|
38
|
-
|
|
38
|
+
if command -v rsync >/dev/null 2>&1; then
|
|
39
|
+
rsync -a --exclude 'target' --exclude 'node_modules' --exclude '.git' "$SOURCE_DIR/" "$dest/"
|
|
40
|
+
else
|
|
41
|
+
cp -R "$SOURCE_DIR/"* "$dest/"
|
|
42
|
+
rm -rf "$dest/services/anti-slop-rust/target" "$dest/node_modules" 2>/dev/null || true
|
|
43
|
+
fi
|
|
39
44
|
# Ensure scripts are executable
|
|
40
45
|
chmod +x "$dest/bin/cli.js" 2>/dev/null || true
|
|
41
46
|
chmod +x "$dest/scripts/diff_guard.py" 2>/dev/null || true
|
|
42
47
|
chmod +x "$dest/scripts/sre_guard.py" 2>/dev/null || true
|
|
43
48
|
chmod +x "$dest/scripts/decision_guard.py" 2>/dev/null || true
|
|
44
49
|
chmod +x "$dest/scripts/root_fix_guard.py" 2>/dev/null || true
|
|
50
|
+
chmod +x "$dest/scripts/future_scale_guard.py" 2>/dev/null || true
|
|
45
51
|
chmod +x "$dest/install.sh" 2>/dev/null || true
|
|
46
52
|
echo " ✅ Installed anti-slop-engineering for ${label} -> ${dest}"
|
|
47
53
|
|
|
48
54
|
# Install each bundled module as a discoverable top-level skill.
|
|
49
|
-
for module in decision-guard root-fix-gate; do
|
|
55
|
+
for module in decision-guard root-fix-gate future-scale-gate; do
|
|
50
56
|
if [ -d "$SOURCE_DIR/skills/$module" ]; then
|
|
51
57
|
local module_dest="$(dirname "$dest")/$module"
|
|
52
58
|
rm -rf "$module_dest"
|
package/marketplace.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-plugin-manifest.json",
|
|
3
3
|
"name": "anti-slop-engineering",
|
|
4
4
|
"displayName": "Anti-Slop Engineering",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.4.0",
|
|
6
6
|
"description": "An Engineering Discipline Playbook, Agent Skill & Triage Guard for AI Coding Agents. Enforces behavioral contracts, focused diffs, test integrity, Google SRE principles, and native Rust/Go clean-room microservices.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Mamdouh Aboammar",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anti-slop-engineering",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "An Engineering Discipline Playbook, Agent Skill & Triage Guard for AI Coding Agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/cli.js",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"homepage": "https://github.com/imMamdouhaboammar/anti-slop-engineering#readme",
|
|
22
22
|
"files": [
|
|
23
23
|
"bin",
|
|
24
|
+
"dist",
|
|
24
25
|
"scripts",
|
|
25
26
|
"skills",
|
|
26
27
|
"services/anti-slop-rust/Cargo.toml",
|
|
@@ -49,6 +50,7 @@
|
|
|
49
50
|
"sre-guard": "bun bin/cli.js sre",
|
|
50
51
|
"test": "python3 -m unittest discover -s tests -v",
|
|
51
52
|
"test-all": "make test-all",
|
|
53
|
+
"bump": "python3 scripts/bump_version.py",
|
|
52
54
|
"check": "make check",
|
|
53
55
|
"check-all": "make check-all"
|
|
54
56
|
},
|
|
@@ -39,6 +39,7 @@ Format: **ID | pattern | how to verify / safer alternative**. Numbers are stable
|
|
|
39
39
|
- **ARC-15 | Manual scaffolding improvisation.** Hand-crafting directory structures, build configs, and boilerplate files (`tsconfig.json`, `package.json`, `pyproject.toml`, Dockerfiles) from memory instead of using the official framework/language CLI installer, starter template, or generator; introduces missing build flags, non-standard layouts, and broken tooling.
|
|
40
40
|
- **ARC-16 | Familiar-stack default and short-horizon choice.** Agent bundles framework, host and database by popularity without testing actual workload, operations, recovery, exit paths or credible future states; compare independent axes, constraints and reversibility. Managed services and VPS are each legitimate where evidence supports them.
|
|
41
41
|
- **ARC-17 | Symptom fan-out and wrong-layer repair.** Agent fixes a repeated symptom separately in many consumers instead of checking the responsible domain or boundary contract; trace writes and reads, compare owner correction with distributed patches, and preserve distinct context-specific policies. A one-file model rewrite is not automatically safer than a justified multi-layer change.
|
|
42
|
+
- **ARC-18 | Present-state foundation trap.** Agent treats the absence of today's workload bottleneck as evidence that future architecture does not matter, permanently coupling semantics, storage or identity to a cheap current implementation. Alternatively it builds speculative high-scale infrastructure without a credible use case. Distinguish hard-to-reverse foundations from replaceable capacity, rank future scenarios by evidence, and test the smallest evolution path before committing.
|
|
42
43
|
|
|
43
44
|
## C. Simplicity, duplication, and code readability
|
|
44
45
|
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
# Copyright (c) 2026 Mamdouh Aboammar <mamdouhfces1997@gmail.com> and contributors
|
|
4
|
+
"""Bump version across repository manifests, documentation, and native services."""
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import datetime
|
|
8
|
+
import hashlib
|
|
9
|
+
import json
|
|
10
|
+
import pathlib
|
|
11
|
+
import shutil
|
|
12
|
+
import sre_compile
|
|
13
|
+
import subprocess
|
|
14
|
+
import sys
|
|
15
|
+
|
|
16
|
+
SEMVER_PATTERN = sre_compile.compile(
|
|
17
|
+
r'^(?P<major>\d{1,8})\.(?P<minor>\d{1,8})\.(?P<patch>\d{1,8})(?:-(?P<prerelease>[0-9A-Za-z.-]{1,50}))?$'
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
MANIFEST_TARGETS = [
|
|
21
|
+
{
|
|
22
|
+
"file": "package.json",
|
|
23
|
+
"pattern": sre_compile.compile(r'("version"\s*:\s*)"[^"]+"'),
|
|
24
|
+
"replacement": r'\g<1>"{version}"',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"file": "pyproject.toml",
|
|
28
|
+
"pattern": sre_compile.compile(r'(version\s*=\s*)"[^"]+"'),
|
|
29
|
+
"replacement": r'\g<1>"{version}"',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"file": ".skills.json",
|
|
33
|
+
"pattern": sre_compile.compile(r'("version"\s*:\s*)"[^"]+"'),
|
|
34
|
+
"replacement": r'\g<1>"{version}"',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"file": "marketplace.json",
|
|
38
|
+
"pattern": sre_compile.compile(r'("version"\s*:\s*)"[^"]+"'),
|
|
39
|
+
"replacement": r'\g<1>"{version}"',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"file": "SKILL.md",
|
|
43
|
+
"pattern": sre_compile.compile(r'(version\s*:\s*)"[^"]+"'),
|
|
44
|
+
"replacement": r'\g<1>"{version}"',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"file": "bin/cli.js",
|
|
48
|
+
"pattern": sre_compile.compile(r'Anti-Slop Engineering CLI \(v[^\)]+\)'),
|
|
49
|
+
"replacement": r'Anti-Slop Engineering CLI (v{version})',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"file": "CITATION.cff",
|
|
53
|
+
"pattern": sre_compile.compile(r'(version\s*:\s*)[^\n]+'),
|
|
54
|
+
"replacement": r'\g<1>{version}',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"file": "CITATION.cff",
|
|
58
|
+
"pattern": sre_compile.compile(r'(date-released\s*:\s*)[^\n]+'),
|
|
59
|
+
"replacement": r'\g<1>{release_date}',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"file": "services/anti-slop-rust/Cargo.toml",
|
|
63
|
+
"pattern": sre_compile.compile(r'(\[package\][\s\S]*?version\s*=\s*)"[^"]+"'),
|
|
64
|
+
"replacement": r'\g<1>"{version}"',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"file": "services/toil-guard-go/pkg/model/types.go",
|
|
68
|
+
"pattern": sre_compile.compile(r'(Version\s*:\s*)"[^"]+"'),
|
|
69
|
+
"replacement": r'\g<1>"{version}"',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"file": "services/toil-guard-go/pkg/server/server.go",
|
|
73
|
+
"pattern": sre_compile.compile(r'("version"\s*:\s*)"[^"]+"'),
|
|
74
|
+
"replacement": r'\g<1>"{version}"',
|
|
75
|
+
},
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def parse_semver(version_str, depth=0, max_depth=100):
|
|
80
|
+
"""Parse semver string into (major, minor, patch, prerelease)."""
|
|
81
|
+
if depth > max_depth:
|
|
82
|
+
return None
|
|
83
|
+
cleaned = version_str.lstrip("v").strip()
|
|
84
|
+
match = SEMVER_PATTERN.match(cleaned)
|
|
85
|
+
if not match:
|
|
86
|
+
return None
|
|
87
|
+
return {
|
|
88
|
+
"major": int(match.group("major")),
|
|
89
|
+
"minor": int(match.group("minor")),
|
|
90
|
+
"patch": int(match.group("patch")),
|
|
91
|
+
"prerelease": match.group("prerelease"),
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def compute_next_version(current_ver, bump_type, depth=0, max_depth=100):
|
|
96
|
+
"""Calculate the next semver string based on bump type or target version."""
|
|
97
|
+
if depth > max_depth:
|
|
98
|
+
raise ValueError("Maximum recursion depth exceeded")
|
|
99
|
+
|
|
100
|
+
candidate = bump_type.lstrip("v").strip()
|
|
101
|
+
if SEMVER_PATTERN.match(candidate):
|
|
102
|
+
return candidate
|
|
103
|
+
|
|
104
|
+
parsed = parse_semver(current_ver)
|
|
105
|
+
if not parsed:
|
|
106
|
+
raise ValueError(f"Current version '{current_ver}' is not valid semver")
|
|
107
|
+
|
|
108
|
+
bump = bump_type.lower()
|
|
109
|
+
if bump == "patch":
|
|
110
|
+
return f"{parsed['major']}.{parsed['minor']}.{parsed['patch'] + 1}"
|
|
111
|
+
if bump == "minor":
|
|
112
|
+
return f"{parsed['major']}.{parsed['minor'] + 1}.0"
|
|
113
|
+
if bump == "major":
|
|
114
|
+
return f"{parsed['major'] + 1}.0.0"
|
|
115
|
+
|
|
116
|
+
raise ValueError(
|
|
117
|
+
f"Invalid bump type or version '{bump_type}'. Choose patch, minor, major, or explicit semver (e.g. 1.3.0)"
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def read_current_version(root_dir, depth=0, max_depth=100):
|
|
122
|
+
"""Read the current canonical version from package.json."""
|
|
123
|
+
if depth > max_depth:
|
|
124
|
+
raise ValueError("Maximum depth exceeded")
|
|
125
|
+
pkg_path = pathlib.Path(root_dir) / "package.json"
|
|
126
|
+
if not pkg_path.is_file():
|
|
127
|
+
raise FileNotFoundError(f"Missing canonical manifest at {pkg_path}")
|
|
128
|
+
data = json.loads(pkg_path.read_text(encoding="utf-8"))
|
|
129
|
+
version = data.get("version")
|
|
130
|
+
if not isinstance(version, str) or not version.strip():
|
|
131
|
+
raise ValueError(f"package.json has missing or invalid version: {version}")
|
|
132
|
+
return version.strip()
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def apply_target_update(compiled_pattern, repl_str, content, depth=0, max_depth=100):
|
|
136
|
+
"""Apply single precompiled regex replacement pattern to file content."""
|
|
137
|
+
if depth > max_depth:
|
|
138
|
+
return content, False
|
|
139
|
+
new_content, count = compiled_pattern.subn(repl_str, content, count=1)
|
|
140
|
+
return new_content, count > 0
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def update_attestation_hash(root_dir, new_pkg_content, depth=0, max_depth=100):
|
|
144
|
+
"""Update package.json sha256 in .fable/heal-attestation.json if present."""
|
|
145
|
+
if depth > max_depth:
|
|
146
|
+
return False
|
|
147
|
+
attestation_path = pathlib.Path(root_dir) / ".fable" / "heal-attestation.json"
|
|
148
|
+
if not attestation_path.is_file():
|
|
149
|
+
return False
|
|
150
|
+
try:
|
|
151
|
+
data = json.loads(attestation_path.read_text(encoding="utf-8"))
|
|
152
|
+
if "file_hashes" in data and "package.json" in data["file_hashes"]:
|
|
153
|
+
new_hash = hashlib.sha256(new_pkg_content.encode("utf-8")).hexdigest()
|
|
154
|
+
data["file_hashes"]["package.json"] = new_hash
|
|
155
|
+
attestation_path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
|
|
156
|
+
return True
|
|
157
|
+
except (OSError, ValueError):
|
|
158
|
+
return False
|
|
159
|
+
return False
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def sync_cargo_lock(root_dir):
|
|
163
|
+
"""Synchronize Cargo.lock if cargo is available."""
|
|
164
|
+
cargo_bin = shutil.which("cargo")
|
|
165
|
+
cargo_toml = pathlib.Path(root_dir) / "services" / "anti-slop-rust" / "Cargo.toml"
|
|
166
|
+
if cargo_bin and cargo_toml.is_file():
|
|
167
|
+
subprocess.run(
|
|
168
|
+
[cargo_bin, "check", "--manifest-path", str(cargo_toml)],
|
|
169
|
+
capture_output=True,
|
|
170
|
+
check=False,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def bump_repository_version(root_dir, bump_type, release_date=None, dry_run=False, depth=0, max_depth=100):
|
|
175
|
+
"""Perform version bump across all registered repository manifests."""
|
|
176
|
+
if depth > max_depth:
|
|
177
|
+
raise ValueError("Maximum depth exceeded")
|
|
178
|
+
root = pathlib.Path(root_dir).resolve()
|
|
179
|
+
current_ver = read_current_version(root)
|
|
180
|
+
next_ver = compute_next_version(current_ver, bump_type)
|
|
181
|
+
rel_date = release_date or datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d")
|
|
182
|
+
|
|
183
|
+
results = []
|
|
184
|
+
file_contents = {}
|
|
185
|
+
|
|
186
|
+
for target in MANIFEST_TARGETS:
|
|
187
|
+
rel_path = target["file"]
|
|
188
|
+
file_path = root / rel_path
|
|
189
|
+
if not file_path.is_file():
|
|
190
|
+
results.append({"file": rel_path, "status": "skipped_missing"})
|
|
191
|
+
continue
|
|
192
|
+
|
|
193
|
+
content = file_contents.get(rel_path)
|
|
194
|
+
if content is None:
|
|
195
|
+
content = file_path.read_text(encoding="utf-8")
|
|
196
|
+
|
|
197
|
+
repl_str = target["replacement"].format(version=next_ver, release_date=rel_date)
|
|
198
|
+
new_content, updated = apply_target_update(target["pattern"], repl_str, content)
|
|
199
|
+
|
|
200
|
+
if updated:
|
|
201
|
+
file_contents[rel_path] = new_content
|
|
202
|
+
results.append({"file": rel_path, "status": "updated"})
|
|
203
|
+
else:
|
|
204
|
+
results.append({"file": rel_path, "status": "pattern_not_found"})
|
|
205
|
+
|
|
206
|
+
if not dry_run:
|
|
207
|
+
for rel_path, content in file_contents.items():
|
|
208
|
+
(root / rel_path).write_text(content, encoding="utf-8")
|
|
209
|
+
|
|
210
|
+
if "package.json" in file_contents:
|
|
211
|
+
update_attestation_hash(root, file_contents["package.json"])
|
|
212
|
+
|
|
213
|
+
sync_cargo_lock(root)
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
"previous_version": current_ver,
|
|
217
|
+
"new_version": next_ver,
|
|
218
|
+
"release_date": rel_date,
|
|
219
|
+
"dry_run": dry_run,
|
|
220
|
+
"updated_files": list(dict.fromkeys(r["file"] for r in results if r["status"] == "updated")),
|
|
221
|
+
"details": results,
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def main():
|
|
226
|
+
"""Command-line entrypoint for bumping version."""
|
|
227
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
228
|
+
parser.add_argument(
|
|
229
|
+
"bump",
|
|
230
|
+
nargs="?",
|
|
231
|
+
default="patch",
|
|
232
|
+
help="Bump type (patch, minor, major) or explicit semver version (e.g. 1.3.0)",
|
|
233
|
+
)
|
|
234
|
+
parser.add_argument("--repo", default=".", help="Root directory of the repository")
|
|
235
|
+
parser.add_argument("--date", default=None, help="Release date override (YYYY-MM-DD)")
|
|
236
|
+
parser.add_argument("--dry-run", action="store_true", help="Preview version changes without writing")
|
|
237
|
+
parser.add_argument("--json", action="store_true", help="Output machine-readable JSON summary")
|
|
238
|
+
parser.add_argument("--git-tag", action="store_true", help="Create git tag vX.Y.Z after bump")
|
|
239
|
+
parser.add_argument("--git-commit", action="store_true", help="Create git commit after bump")
|
|
240
|
+
args = parser.parse_args()
|
|
241
|
+
|
|
242
|
+
try:
|
|
243
|
+
report = bump_repository_version(
|
|
244
|
+
root_dir=args.repo,
|
|
245
|
+
bump_type=args.bump,
|
|
246
|
+
release_date=args.date,
|
|
247
|
+
dry_run=args.dry_run,
|
|
248
|
+
)
|
|
249
|
+
except (ValueError, FileNotFoundError) as err:
|
|
250
|
+
print(f"Error: {err}", file=sys.stderr)
|
|
251
|
+
return 1
|
|
252
|
+
|
|
253
|
+
if args.git_commit and not args.dry_run:
|
|
254
|
+
ver = report["new_version"]
|
|
255
|
+
subprocess.run(["git", "-C", args.repo, "add", "-A"], check=False)
|
|
256
|
+
subprocess.run(["git", "-C", args.repo, "commit", "-m", f"chore(release): v{ver}"], check=False)
|
|
257
|
+
|
|
258
|
+
if args.git_tag and not args.dry_run:
|
|
259
|
+
ver = report["new_version"]
|
|
260
|
+
subprocess.run(["git", "-C", args.repo, "tag", "-a", f"v{ver}", "-m", f"Release v{ver}"], check=False)
|
|
261
|
+
|
|
262
|
+
if args.json:
|
|
263
|
+
print(json.dumps(report, indent=2))
|
|
264
|
+
else:
|
|
265
|
+
status_prefix = "[DRY-RUN] " if report["dry_run"] else ""
|
|
266
|
+
print(f"{status_prefix}Bumped version: v{report['previous_version']} ➜ v{report['new_version']}")
|
|
267
|
+
print(f"Release Date: {report['release_date']}")
|
|
268
|
+
print(f"Updated {len(set(report['updated_files']))} manifest files:")
|
|
269
|
+
for file in sorted(set(report["updated_files"])):
|
|
270
|
+
print(f" ✓ {file}")
|
|
271
|
+
|
|
272
|
+
return 0
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
if __name__ == "__main__":
|
|
276
|
+
sys.exit(main())
|