Skip to content

Commit 6638a1e

Browse files
Create thing-golf.md
1 parent 2249f3b commit 6638a1e

File tree

1 file changed

+203
-0
lines changed

1 file changed

+203
-0
lines changed

research/thing-golf.md

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
---
2+
canonical-url: https://gist.githubusercontent.com/subtleGradient/baf6fbf62c39ff434894f6676a1b1e28/raw/88eb4866b3e71692192a8cb037ea791ec1a0d0f0/thing-golf.AGENTS.md
3+
---
4+
5+
# Thing Golf v3.1 – Fear/Pain Aware PR Scoring (TS Monorepos)
6+
7+
Target: future AI/LLM selves with tools (git diff, FS, AST, config parsers).
8+
Domain: TypeScript monorepo PRs.
9+
10+
---
11+
12+
## 0. Core Idea
13+
14+
Don’t measure lines or characters.
15+
16+
Measure **how much more dangerous, heavy, chaotic, betraying, and controlling** the repo becomes when a PR is merged.
17+
18+
- Unit: **ThingBadness**
19+
- Baseline: **0 = neutral**
20+
- **Higher is always worse.** Negative changes are good (they remove badness).
21+
22+
---
23+
24+
## 1. Thing
25+
26+
A **Thing** is one named concept delta in the PR.
27+
28+
Examples (each is a separate Thing):
29+
30+
- New / changed / deleted exported function, const, type, interface, class, enum, component.
31+
- New / removed module that is imported somewhere.
32+
- New / removed workspace package.
33+
- New / removed dependency in `package.json`.
34+
- New / changed / removed HTTP route or RPC handler.
35+
- New / changed / removed CLI command or subcommand.
36+
- New / changed / removed DB migration file.
37+
- New / changed / removed CI workflow, job, or matrix axis.
38+
- New / changed / removed env var usage (`process.env.*` etc).
39+
- New / changed / removed test file or top-level test suite.
40+
- New / changed / removed doc page or major section.
41+
42+
**Granularity rule:** count by **named unit**, not by lines.
43+
44+
Each Thing has:
45+
46+
- `change` ∈ { `NEW`, `MODIFY`, `DELETE` }
47+
48+
---
49+
50+
## 2. Good vs Bad Slices
51+
52+
We slice Things along **monotonic good/bad axes**.
53+
54+
For every slice:
55+
56+
- **Left = good direction** (less fear/pain).
57+
- **Right = bad direction** (more fear/pain).
58+
- Scoring only adds when a Thing leans to the **right** side.
59+
60+
### 2.1 The slices (labels + intuition)
61+
62+
1. **Safety vs Explosiveness**
63+
- Left: **Safe** – unlikely to cause surprising breakage.
64+
- Right: **Explosive** – likely to blow up prod or create landmines.
65+
66+
2. **Lightness vs Legacy Burden**
67+
- Left: **Lighter** – fewer obligations in the future.
68+
- Right: **Heavier** – more long-term stuff to maintain.
69+
70+
3. **Clarity vs Chaos**
71+
- Left: **Clearer** – easier to understand and reason about.
72+
- Right: **Chaotic** – harder to understand; more tangled.
73+
74+
4. **Trustworthy vs Betraying**
75+
- Left: **Trustworthy** – increases others’ ability to rely on the system and on you.
76+
- Right: **Betraying** – sets people up to be burned or misled.
77+
78+
5. **Freedom vs Control-Freak**
79+
- Left: **Freer** – more healthy autonomy and flexibility.
80+
- Right: **Control-Freak** – more rigid knobs, micro-config, coupling.
81+
82+
---
83+
84+
## 3. Fear/Pain meaning
85+
86+
Tie each bad side to human needs:
87+
88+
- **Explosive** → attacks **certainty** and **significance**
89+
(“If this explodes, I look incompetent and everything is on fire.”)
90+
91+
- **Heavier** → attacks **freedom** and **variety**
92+
(“I’ll spend my life servicing this instead of choosing what to work on.”)
93+
94+
- **Chaotic** → attacks **certainty**
95+
(“I can’t even tell what this does anymore.”)
96+
97+
- **Betraying** → attacks **connection** and **significance**
98+
(“People will stop trusting me / us if this blows up or leaks.”)
99+
100+
- **Control-Freak** → attacks **freedom** and **variety**
101+
(“I need a ritual and 7 flags just to touch this.”)
102+
103+
---
104+
105+
## 4. Slice Table (with examples)
106+
107+
All examples are TS monorepo PR deltas.
108+
109+
| Slice label | Left label (good) | Right label (bad) | Left examples (good side) | Right examples (bad side) |
110+
| --- | --- | --- | --- | --- |
111+
| **Safety vs Explosiveness** | **Safe** | **Explosive** | Adding tests for existing behavior; making a dangerous CLI command safer (extra confirmation); adding idempotency to an endpoint; adding runtime guards on inputs | Adding a new public API without tests; adding a destructive CLI subcommand; introducing a breaking DB migration on a critical table; removing validation to “fix” performance |
112+
| **Lightness vs Legacy Burden** | **Lighter** | **Heavier** | Deleting unused modules; removing dead feature flags; removing unused dependencies; replacing 3 overlapping libs with 1 | Adding a new workspace package; adding a new long-term feature flag; introducing another cross-cutting util used everywhere; adding a new persistent queue/topic/cron |
113+
| **Clarity vs Chaos** | **Clearer** | **Chaotic** | Splitting a God-object into well-named focused modules; adding clear docs; adding tests that document edge cases; consistent renames to better names | Adding a “misc.ts” dumping ground; adding `any` casts that bypass types; adding branches without docs or tests; mixing unrelated concerns into one mega-file or mega-util |
114+
| **Trustworthy vs Betraying** | **Trustworthy** | **Betraying** | Fixing flaky tests; making CI more honest (no hiding failures); improving health checks; clarifying error messages | Marking flaky tests `skip` to get green CI; logging PII in plain text; adding a “debug backdoor” endpoint; silently ignoring errors to “keep it running” |
115+
| **Freedom vs Control-Freak** | **Freer** | **Control-Freak** | Simplifying config (one typed config object instead of 12 envs); collapsing redundant feature flags; removing unnecessary CI steps; loosening over-strict rules that block harmless work | Adding yet another boolean env flag; adding per-team, per-region, per-tenant special cases; coupling many modules to one central “manager”; adding blocking approvals for trivial changes |
116+
117+
---
118+
119+
## 5. Scoring Model
120+
121+
For each Thing `T`, we compute **five per-axis contributions**:
122+
123+
- `SafetyBad(T)` ∈ ℤ (≥ 0)
124+
- `BurdenBad(T)` ∈ ℤ (can be negative if we remove burden)
125+
- `ChaosBad(T)` ∈ ℤ (≥ 0, can be negative if we remove chaos)
126+
- `BetrayalBad(T)` ∈ ℤ (≥ 0)
127+
- `ControlFreakBad(T)` ∈ ℤ (≥ 0, can be negative if we remove control)
128+
129+
### 5.1 Base by change kind (Legacy Burden)
130+
131+
This axis captures **past vs future load**:
132+
133+
- `NEW``BurdenBad += +2`
134+
- `MODIFY``BurdenBad += 0`
135+
- `DELETE``BurdenBad += -2`
136+
137+
All other axes default to `0` unless the Thing has properties that push it rightward.
138+
139+
### 5.2 Heuristic bumps per axis
140+
141+
These are simple, monotonic “badness” rules:
142+
143+
#### Safety vs Explosiveness
144+
145+
- If Thing touches **runtime behavior in prod** (code path that executes in prod, DB schema/data, routing, CLI used in prod):
146+
- `SafetyBad += 1`
147+
- If Thing is **destructive** (delete/update bulk data, destructive CLI, risky migration):
148+
- `SafetyBad += 2`
149+
- If Thing **removes safety** (removes validation, removes error handling, bypasses types with `any`):
150+
- `SafetyBad += 2`
151+
- If Thing **adds explicit safety** (new validation, circuit breaker, idempotency, rollback path):
152+
- `SafetyBad += -1` (safer)
153+
154+
#### Lightness vs Legacy Burden
155+
156+
Already covered by NEW/MODIFY/DELETE, plus:
157+
158+
- If Thing is a new **public runtime surface** (exported API, route, CLI command, queue/cron):
159+
- `BurdenBad += 2`
160+
- If Thing is a new **cross-cutting dependency** (kitchen sink util, new global manager, new global config):
161+
- `BurdenBad += 2`
162+
- If Thing **removes** such a surface or dependency:
163+
- `BurdenBad += -2`
164+
165+
#### Clarity vs Chaos
166+
167+
- If Thing **adds structure** (more precise types, strict TS, clear module boundaries, better naming, docs/tests that document behavior):
168+
- `ChaosBad += -1`
169+
- If Thing **punches holes in structure** (casts to `any`, “misc.ts”, dumping unrelated behaviors together, magic strings, ad-hoc conditionals):
170+
- `ChaosBad += +2`
171+
- If Thing **multiplies branches** without documentation/tests:
172+
- `ChaosBad += +1`
173+
174+
#### Trustworthy vs Betraying
175+
176+
- If Thing **makes signals more honest** (fix flakiness, make CI reflect truth, better error messages, stronger invariants):
177+
- `BetrayalBad += -1`
178+
- If Thing **lies or hides failure** (skip tests to get green, swallow errors, ignore results silently):
179+
- `BetrayalBad += +2`
180+
- If Thing **puts user/team at risk** (PII logging, backdoors, silent data loss):
181+
- `BetrayalBad += +3`
182+
183+
#### Freedom vs Control-Freak
184+
185+
- If Thing **removes unnecessary knobs** (fewer flags, simpler config, fewer approval gates, less centralization):
186+
- `ControlFreakBad += -1`
187+
- If Thing **adds knobs and approvals** (new env flags, new mandatory approvals, central manager that everything must go through):
188+
- `ControlFreakBad += +1` (small), up to `+3` for very heavy centralization.
189+
- If Thing **deeply couples** many modules to one “god” object:
190+
- `ControlFreakBad += +2`
191+
192+
---
193+
194+
## 6. Per-Thing and PR-Level Scores
195+
196+
For each Thing `T`:
197+
198+
```text
199+
ThingBadness(T) = w_safety * SafetyBad(T)
200+
+ w_burden * BurdenBad(T)
201+
+ w_chaos * ChaosBad(T)
202+
+ w_betrayal * BetrayalBad(T)
203+
+ w_control * ControlFreakBad(T)

0 commit comments

Comments
 (0)