@stupify/cli 0.0.15 → 0.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.
Files changed (74) hide show
  1. package/.review/CORPUS.md +73 -0
  2. package/.review/REVIEW-PROMPT.md +52 -0
  3. package/.review/RUBRIC.md +46 -0
  4. package/LICENSE +1 -1
  5. package/README.md +41 -39
  6. package/package.json +24 -25
  7. package/src/cli.ts +358 -0
  8. package/src/review-sweep.ts +492 -0
  9. package/dist/analysis.d.ts +0 -16
  10. package/dist/analysis.js +0 -165
  11. package/dist/cache.d.ts +0 -2
  12. package/dist/cache.js +0 -57
  13. package/dist/checks.d.ts +0 -4
  14. package/dist/checks.js +0 -228
  15. package/dist/command.d.ts +0 -2
  16. package/dist/command.js +0 -147
  17. package/dist/constants.d.ts +0 -4
  18. package/dist/constants.js +0 -53
  19. package/dist/counter-scout.d.ts +0 -21
  20. package/dist/counter-scout.js +0 -167
  21. package/dist/diff.d.ts +0 -1
  22. package/dist/diff.js +0 -10
  23. package/dist/doctor.d.ts +0 -4
  24. package/dist/doctor.js +0 -131
  25. package/dist/git.d.ts +0 -12
  26. package/dist/git.js +0 -298
  27. package/dist/hooks.d.ts +0 -3
  28. package/dist/hooks.js +0 -117
  29. package/dist/index.d.ts +0 -1
  30. package/dist/index.js +0 -1
  31. package/dist/model.d.ts +0 -11
  32. package/dist/model.js +0 -296
  33. package/dist/prompts.d.ts +0 -8
  34. package/dist/prompts.js +0 -89
  35. package/dist/render.d.ts +0 -3
  36. package/dist/render.js +0 -151
  37. package/dist/repomix-provider.d.ts +0 -12
  38. package/dist/repomix-provider.js +0 -196
  39. package/dist/search-bench.d.ts +0 -1
  40. package/dist/search-bench.js +0 -677
  41. package/dist/search-profile.d.ts +0 -6
  42. package/dist/search-profile.js +0 -73
  43. package/dist/sem-provider.d.ts +0 -2
  44. package/dist/sem-provider.js +0 -252
  45. package/dist/stupify.d.ts +0 -38
  46. package/dist/stupify.js +0 -474
  47. package/dist/trace.d.ts +0 -31
  48. package/dist/trace.js +0 -86
  49. package/dist/types.d.ts +0 -328
  50. package/dist/types.js +0 -6
  51. package/dist/ui.d.ts +0 -34
  52. package/dist/ui.js +0 -143
  53. package/src/analysis.ts +0 -220
  54. package/src/cache.ts +0 -63
  55. package/src/checks.ts +0 -231
  56. package/src/command.ts +0 -173
  57. package/src/constants.ts +0 -56
  58. package/src/counter-scout.ts +0 -195
  59. package/src/diff.ts +0 -9
  60. package/src/doctor.ts +0 -140
  61. package/src/git.ts +0 -306
  62. package/src/hooks.ts +0 -134
  63. package/src/index.ts +0 -1
  64. package/src/model.ts +0 -367
  65. package/src/prompts.ts +0 -100
  66. package/src/render.ts +0 -154
  67. package/src/repomix-provider.ts +0 -219
  68. package/src/search-bench.ts +0 -783
  69. package/src/search-profile.ts +0 -89
  70. package/src/sem-provider.ts +0 -297
  71. package/src/stupify.ts +0 -571
  72. package/src/trace.ts +0 -126
  73. package/src/types.ts +0 -348
  74. package/src/ui.ts +0 -187
@@ -0,0 +1,73 @@
1
+ # Good-code reference — YOUR curated exemplars (template)
2
+
3
+ > This is a template. **Replace it with 3–6 files from your own codebase that you'd point a new hire at** —
4
+ > the code you wish all your code looked like. The reviewer treats these as the standard and measures every
5
+ > diff against them. Taste can't be auto-extracted: hand-pick these, and say *why* each is good. A vague
6
+ > corpus produces vague reviews; a sharp one produces sharp ones.
7
+
8
+ How to write an entry:
9
+ - **Name the file** (a real path in this repo) and **one sentence on what makes it good** — the principle it
10
+ embodies (e.g. "complexity tamed by decomposition", "type makes illegal states unrepresentable",
11
+ "fail-fast at the boundary"). The reviewer opens the live file; the excerpt just shows the shape.
12
+ - Keep a short code excerpt that captures the pattern. The point is the *principle*, not the lines.
13
+ - Group loosely (e.g. "complex but readable", "clean service boundary") so the reviewer can cite the right one.
14
+
15
+ Pick principles you actually care about. Common ones worth encoding:
16
+ **dependency injection** (collaborators injected, never `new`d inline; config read only at a composition root),
17
+ **type-system-first invariants** (`satisfies`, discriminated unions, schemas at boundaries — illegal states
18
+ hard to represent), **fail fast and loud** (no silent fallback), **small single-responsibility units**,
19
+ **declarative over imperative**, **readable signatures** (≤3 positional params → options object).
20
+
21
+ ---
22
+
23
+ ## A. Complex, kept readable
24
+
25
+ ### 1. `src/path/to/your-exemplar.ts` — one line on why it's good
26
+ `src/path/to/your-exemplar.ts`
27
+
28
+ Say what makes it the standard — e.g. the complexity (optimistic UI, retries, sync) is tamed by decomposition:
29
+ the orchestrator only *coordinates*; every concern is a small focused unit, and every operation is the same
30
+ shape, so N of them read like one.
31
+
32
+ ```ts
33
+ // a short excerpt that shows the pattern — the shape, not the whole file
34
+ export function handle(input: Input): Result {
35
+ const state = read()
36
+ const ops = compute(state, input) // pure
37
+ return apply(ops) // effectful shell
38
+ }
39
+ ```
40
+
41
+ ### 2. `src/path/to/another.ts` — composition + named pieces
42
+ `src/path/to/another.ts`
43
+
44
+ e.g. pure composition — each piece a named small component, conditions become named type-guards, not inline
45
+ boolean soup.
46
+
47
+ ```ts
48
+ function hasMeasuredWidth(width: number | undefined): width is number {
49
+ return width !== undefined && width > 0
50
+ }
51
+ ```
52
+
53
+ ---
54
+
55
+ ## B. Clean boundary / DI
56
+
57
+ ### `src/path/to/service.ts` — injected collaborator + composition-root factory
58
+ `src/path/to/service.ts`
59
+
60
+ e.g. constructor injection — the collaborator is never `new`d inline; a small factory is the composition root;
61
+ the method parses input at the boundary, logs with structured context, and **fails loud** (catch → log → rethrow).
62
+
63
+ ```ts
64
+ export function createService() {
65
+ const scope = container.createChildContainer()
66
+ scope.register(CLIENT, { useValue: makeClient() })
67
+ return scope.resolve(Service)
68
+ }
69
+ ```
70
+
71
+ ---
72
+
73
+ > Add a "Fine — do NOT flag" set of your own here too, if there are patterns reviewers keep wrongly dinging.
@@ -0,0 +1,52 @@
1
+ # Review spec — corpus-grounded, anti-slop, with a personality
2
+
3
+ You are reviewing a code diff for this repo. You're running in the repo with `gh` / `git` / file access and
4
+ your own model — no API key needed. Run these steps:
5
+
6
+ 1. Read `RUBRIC.md` (the anti-slop rubric + finding taxonomy) and `CORPUS.md` (this team's curated "good code"
7
+ — the primitives it actually uses). Treat the corpus as the standard. Open the live files it points at.
8
+ 2. Get the diff for the target PR.
9
+ 3. Review every changed code file (skip lockfiles, generated/snapshot files, pure deletions). Catch BOTH
10
+ kinds from the rubric — the "just wrong" (bug / type-lie / dead-code / footgun) and the "taste / reuse"
11
+ (reinvents-primitive / slop). "Slop" is code RELATIVE to the simpler or already-existing way: does it
12
+ reinvent a corpus primitive, or is it bigger / more abstract / more speculative than the corpus pattern for
13
+ the same job? When you cite a fix, name the actual corpus file/primitive it should use.
14
+ 4. Format the review per the **Comment format** below. Report everything incl. low-confidence; don't self-filter.
15
+ 5. Post it with the `gh pr comment` command you were given (write the comment to the file, then post).
16
+
17
+ ## Prior reviews on this PR (your memory)
18
+
19
+ If the runner hands you a **"Prior reviews on this PR"** block, it's the existing review conversation — your
20
+ past reviews and the author's replies. You are CONTINUING that thread, not starting fresh. Treat it as memory:
21
+
22
+ - **Don't re-raise what's settled.** If you already flagged something and it's now fixed, or the author
23
+ **declined it with a reason**, do not raise it again — unless the diff brings new evidence that actually
24
+ rebuts their reason. Re-litigating a reasoned decline is noise (and the fastest way to be ignored).
25
+ - **Report only what's new.** Surface issues introduced since your last review, or ones you genuinely missed.
26
+ Do not manufacture marginal findings just to have something to say — a nit you wouldn't have raised on
27
+ round one doesn't become worth raising on round six.
28
+ - **Converge — knowing when to stop is part of the job.** If there are no new issues and the prior ones are
29
+ addressed or reasonably declined, do NOT write a review. Post exactly this line and nothing else:
30
+ `no new blocking issues — prior items addressed ✅`
31
+
32
+ (No prior-reviews block = this is the first review of this PR; ignore this section.)
33
+
34
+ ## Comment format (GitHub markdown — warm + scannable)
35
+
36
+ - **Opening line — write it yourself: direct, genuinely silly, honest.** ONE short, lowercase-casual line —
37
+ goofy human noises, drawn-out exclamations, mild swears, the way someone reacts while scrolling code:
38
+ "uhhhh ummm", "shieeeeet", "oof", "ohhh boy", "ok so… yeah". NOT corporate, NOT clever-witty, NOT a linter
39
+ header, no praise-padding. Be a little dumb on purpose, then get to what you found. Vary it every run:
40
+ - nothing wrong → `yep. clean. no notes 🎉` and **stop** (no blocks).
41
+ - a few small things → `uhhhh ummm a couple things 👇` · `shieeeeet, found some stuff:` · `ok so. some stuff:`
42
+ - something real → `oh no. ok there's a real one in here:` · `oof, yeah this'll break:`
43
+ Then a blank line. (Tune this register to your taste — or delete it for a dry tone.)
44
+ - **Each finding** worst-first, as a 3-line block with a blank line between blocks:
45
+ - line 1: `<emoji> **`path:line`** · <kind> · conf <0–1>`
46
+ - line 2: what's wrong and why (1–2 sentences, plain — describe the code, don't scold)
47
+ - line 3: `**→ Fix:** <corpus primitive to reuse, or the correct approach> (`<reference file>`)`
48
+ - Severity emoji: 🔴 high · 🟠 med · 🟡 low.
49
+ - Close with a quiet attribution on its own line so it's clearly the auto-reviewer, not a person:
50
+ `_— stupify, against the good-code corpus_`
51
+ - No tables, no nested bullets, no preamble before the opener. End the comment with the exact hidden marker
52
+ line you were given.
@@ -0,0 +1,46 @@
1
+ # Anti-slop rubric — the single source of truth for taste
2
+
3
+ This is what the reviewer judges against, alongside `CORPUS.md`. Edit it to match your team. A reviewer
4
+ catches two kinds of problem. Tag every finding with its `kind`.
5
+
6
+ ## Just wrong — flag regardless of the corpus
7
+ - `kind: bug` — correctness bugs; off-by-one; broken null/empty handling; wrong condition.
8
+ - `kind: type-lie` — a type/annotation that does not match what the code actually returns
9
+ (e.g. annotated `T | null` but every path returns a non-null value cast to `T`).
10
+ - `kind: dead-code` — unreachable or dead branches; a declared-and-unused const/import/function.
11
+ - `kind: footgun` — swallowed errors / catch-and-continue with no owned degraded state; silent fallbacks;
12
+ test-only special-casing (`NODE_ENV === 'test'`, env-name string checks) leaking into production code.
13
+
14
+ ## Taste / reuse — relative to the corpus and the simpler way
15
+ - `kind: reinvents-primitive` — a NEW abstraction/layer/wrapper/facade/shim/fallback-reader when a corpus
16
+ primitive already does it (name the primitive). Or hand-rolling what a corpus file does.
17
+ - `kind: slop` — bigger / more abstract / more speculative than the corpus pattern for the same job:
18
+ - speculative `unknown` in hand-authored types; `TResult = unknown` generic defaults;
19
+ `z.unknown()` / `z.array(z.unknown())`
20
+ - generic-parameter explosion on a call site that is not actually reused generically
21
+ - `let best*/latest*` imperative argmax/latest accumulator loops
22
+ - throwaway one-call helpers, or wrapper functions that add no value — a pure pass-through to another fn
23
+ with the same signature; inline it / call the inner directly
24
+ - a defensive `?.` / `??` fallback on a value the type or schema already guarantees — e.g. `x?.foo ?? x.y.foo`
25
+ when `x` is required (or should be). Drop the optional chain and the fallback (it's `x.foo`); if `x` is
26
+ wrongly optional, fix the schema/type, don't paper over it at the call site
27
+ - denormalized parallel constants or hardcoded membership lists (derive a Set/Record from ONE `as const` array)
28
+ - speculative config seams / unused `mode` switches / injectable-override defaults nothing needs yet
29
+ - additive churn on a cleanup; code that "looks productive" over the minimal change
30
+
31
+ ## Fine — do NOT flag
32
+ - `unknown` at a real parse boundary fed into a normalizer; `Record<string, unknown>` context bags
33
+ - Set/Map-building or dedupe loops (not argmax accumulators)
34
+ - a single choke-point helper its owner reuses
35
+
36
+ ## Weigh the fix against the owner
37
+ Right-size the remedy to the code that owns it. Don't prescribe a heavier primitive than the context warrants:
38
+ a one-off script shouldn't grow a schema library, glue code shouldn't sprout an interface, a guaranteed-shape
39
+ boundary doesn't need the validation an untrusted one does, and an unattended job usually wants a loud default
40
+ over a hard exit. Demanding more rigor than the owner needs is its own slop. If the minimal fix is a one-liner,
41
+ the fix is the one-liner — propose that, not an architecture.
42
+
43
+ ## Output per finding
44
+ `path:line` — [kind] — what's wrong and why — **fix:** the corpus primitive to reuse OR (for a bug) the
45
+ correct approach — severity(high|med|low) · confidence(0–1). Sort worst-first. Report everything incl.
46
+ low-confidence — do not self-filter; a downstream ranker (and your own memory) handles that.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Stupify contributors
3
+ Copyright (c) 2026 Noah Lindner
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,58 +1,60 @@
1
- # @stupify/cli
1
+ # stupify
2
2
 
3
- Local-only diagnostic CLI for checking whether AI is making you dumber.
3
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
4
4
 
5
- Released under the MIT License.
5
+ **A code reviewer that talks like an idiot and catches real bugs.**
6
6
 
7
- Stupify has one analysis path:
7
+ > uhhhh ummm a couple things 👇
8
+ >
9
+ > 🔴 **`src/checkout/session.ts:88`** · footgun · conf 0.9
10
+ > if `stripe.retrieve()` throws, the `catch` returns an empty cart — a transient blip looks like an empty order.
11
+ > **→ Fix:** rethrow with context, like the fail-loud boundary in `payment-service.ts`.
12
+ >
13
+ > _— stupify, against the good-code corpus_
8
14
 
9
- ```text
10
- sem diff -> counter scout -> Repomix context -> local search model
11
- ```
12
-
13
- It emits search `matches`, not audit findings.
15
+ Reviews your PRs on [Codex](https://github.com/openai/codex), against a corpus of code **you** picked:
14
16
 
15
- ```sh
16
- npx @stupify/cli --staged
17
- npx @stupify/cli --since "2 weeks ago"
18
- npx @stupify/cli --commit HEAD
19
- npx @stupify/cli --commits 20
20
- git diff HEAD~1..HEAD | npx @stupify/cli --stdin
21
- ```
17
+ - 🎯 **Your taste.** Hand-pick your best files into `CORPUS.md`; it judges diffs against *that*, and cites them.
18
+ - 🧹 **Anti-slop.** `RUBRIC.md` defines slop for your team, and it right-sizes the fix to the owner.
19
+ - 🧠 **Remembers + converges.** Fed the PR's thread, so it won't re-raise what you fixed or declined — and posts `no new blocking issues ✅` and stops.
20
+ - 😂 **A personality.** `oof, yeah this'll break:` … then gets to the point. (Tunable.)
22
21
 
23
- Install the warn-only pre-commit hook:
22
+ A finder, not a gatekeeper — it comments, it doesn't block merges.
24
23
 
25
- ```sh
26
- stupify hook install
27
- ```
24
+ ## Quickstart
28
25
 
29
- The hook runs `stupify --staged` and exits 0.
26
+ Stupify runs on an always-on box, so it rides [exe.dev](https://exe.dev). From your laptop, **one command provisions everything** — it detects your repo, wires the GitHub integration, and spins up a VM that installs itself. No keys, no tokens, you never SSH anywhere:
30
27
 
31
- Check local setup:
28
+ ```bash
29
+ bunx github:Octember/stupif.ai
30
+ ```
32
31
 
33
- ```sh
34
- stupify doctor
32
+ ```
33
+ stupify provision a reviewer on exe.dev
34
+ ◇ using integration acme-widgets
35
+ ◇ VM stupify-acme-widgets created
36
+ └ stupify is provisioned for acme/widgets 👀
35
37
  ```
36
38
 
37
- Default search enables the checks that currently pass the local hook-safety
38
- bench: `duplicated_schema`, `unnecessary_complexity`, `over_commenting`,
39
- `lint_bypass`, and `reinvented_utils`. Other registry patterns can be opted in
40
- with `--checks`.
39
+ First time on exe.dev? `ssh exe.dev` to onboard, link GitHub at [exe.dev/integrations](https://exe.dev/integrations). Then give it your taste — copy [`.review/`](.review) into your repo and point `CORPUS.md` at your best files. Label a PR `codex-review` (or add [`autolabel.yml`](.github/workflows/autolabel.yml)) → a review in ~60s.
41
40
 
42
- ```sh
43
- stupify --staged --checks over_commenting
41
+ ```bash
42
+ bunx github:Octember/stupif.ai <owner/repo> # provision for a specific repo
43
+ ssh exe.dev rm stupify-<owner>-<repo> # tear it down
44
+ bunx github:Octember/stupif.ai setup # install on this machine instead of a VM
44
45
  ```
45
46
 
46
- Large search inputs are skipped rather than truncated:
47
+ ## How it works
47
48
 
48
- ```sh
49
- stupify --staged --max-search-input-tokens 24000
50
49
  ```
50
+ cron (~60s) → review-sweep.ts → codex exec → gh pr comment
51
+ refresh checkout · list labelled PRs · skip already-reviewed heads
52
+ feed the PR's thread back as memory · review against .review/* · post
53
+ ```
54
+
55
+ The CLI (`src/cli.ts`) provisions; the engine (`src/review-sweep.ts`, dependency-free Bun) sweeps; the taste
56
+ (`.review/`) lives in the repo it judges. Details in [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
51
57
 
52
- The package is prepared for the public `@stupify` npm scope. Publishing should
53
- use the repository release workflow so npm receives Trusted Publishing
54
- provenance. See the repository release docs.
58
+ ## License
55
59
 
56
- This iteration intentionally does not run findings audit, validators, judges,
57
- baselines, hosted LLM APIs, GitHub integration, dashboards, or repo-wide
58
- crawling.
60
+ [MIT](LICENSE) © Noah Lindner. `stupif.ai` read it "stupify".
package/package.json CHANGED
@@ -1,53 +1,52 @@
1
1
  {
2
2
  "name": "@stupify/cli",
3
- "version": "0.0.15",
4
- "description": "Local-only diagnostic CLI for checking whether AI is making you dumber.",
5
- "private": false,
3
+ "version": "0.1.0",
4
+ "description": "A code reviewer that talks like an idiot and catches real bugs — corpus-grounded, anti-slop, runs on Codex.",
6
5
  "type": "module",
7
6
  "bin": {
8
- "stupify": "dist/stupify.js"
7
+ "stupify": "src/cli.ts"
9
8
  },
9
+ "files": [
10
+ "src",
11
+ ".review",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "license": "MIT",
16
+ "homepage": "https://stupif.ai",
10
17
  "repository": {
11
18
  "type": "git",
12
- "url": "git+https://github.com/Octember/stupif.ai.git",
13
- "directory": "packages/cli"
19
+ "url": "git+https://github.com/Octember/stupif.ai.git"
14
20
  },
15
- "homepage": "https://stupif.ai",
16
21
  "bugs": {
17
22
  "url": "https://github.com/Octember/stupif.ai/issues"
18
23
  },
19
24
  "keywords": [
25
+ "code-review",
26
+ "codex",
20
27
  "ai",
21
- "cli",
28
+ "pull-request",
22
29
  "developer-tools",
23
- "local-first",
24
- "code-review"
30
+ "anti-slop"
25
31
  ],
26
- "license": "MIT",
27
32
  "engines": {
28
- "node": ">=20"
33
+ "bun": ">=1.3"
29
34
  },
30
35
  "publishConfig": {
31
36
  "access": "public",
32
37
  "provenance": true
33
38
  },
34
- "files": [
35
- "dist",
36
- "src",
37
- "LICENSE",
38
- "README.md",
39
- "package.json"
40
- ],
41
39
  "scripts": {
42
- "build": "tsc -p tsconfig.build.json",
43
- "prepack": "bun run build",
44
40
  "typecheck": "tsc -p tsconfig.json",
45
- "smoke": "bun run build && node ./dist/stupify.js --help"
41
+ "cli": "bun src/cli.ts"
46
42
  },
47
43
  "dependencies": {
48
- "@ataraxy-labs/sem": "^0.3.24",
49
44
  "@clack/prompts": "^1.2.0",
50
- "picocolors": "^1.1.1",
51
- "repomix": "^1.14.0"
45
+ "picocolors": "^1.1.1"
46
+ },
47
+ "devDependencies": {
48
+ "@types/bun": "^1.3.14",
49
+ "@types/node": "^22.10.2",
50
+ "typescript": "^5.7.2"
52
51
  }
53
52
  }