Skip to content

Commit 86b0597

Browse files
committed
feat: split rules into code/ and llm/ directories
Two distinct rule systems: - rules/code/ — programmatic checks (validity, media, spam, content, scoring) executed deterministically in the pipeline, produce pass/fail results - rules/llm/ — natural-language instructions (evaluation, tone, spam-detection, output-format) injected into the LLM system prompt by priority order LLM rules support conditional injection (e.g. only when spam > 0.5). Both types hot-reloadable via POST /api/v1/rules/reload. Updated types, loader, engine, pipeline, README, and docs/RULES.md.
1 parent 70e342d commit 86b0597

File tree

16 files changed

+745
-268
lines changed

16 files changed

+745
-268
lines changed

README.md

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ flowchart LR
4040
MEDIA[Media Check] --> SPAM[Spam Detection]
4141
SPAM --> DUP[Duplicate Detection]
4242
DUP --> EDIT[Edit History]
43-
EDIT --> RULES[Rules Engine]
44-
RULES --> LLM["LLM Gate\n(Gemini 3.1 Pro)"]
43+
EDIT --> CODE["Code Rules\n(rules/code/)"]
44+
CODE --> LLM["LLM Gate\n+ LLM Rules\n(rules/llm/)"]
4545
end
4646
4747
subgraph Output
@@ -66,8 +66,8 @@ Each issue passes through six stages. A failure at any stage short-circuits to a
6666
| **Spam** | Template similarity, burst frequency, parity scoring | `invalid` |
6767
| **Duplicate** | Jaccard + Qwen3 cosine hybrid (`0.4J + 0.6C`) | `duplicate` |
6868
| **Edit History** | Suspicious post-submission edits (evidence swaps) | `invalid` |
69-
| **Rules** | Configurable rules from `rules/*.ts` | `invalid` or penalty |
70-
| **LLM Gate** | Gemini 3.1 Pro with `deliver_verdict` tool calling | `invalid` |
69+
| **Code Rules** | Programmatic checks from `rules/code/*.ts` | `invalid` or penalty |
70+
| **LLM Gate** | Gemini 3.1 Pro + LLM instructions from `rules/llm/*.ts` | `invalid` |
7171

7272
If all stages pass, the issue is labeled **valid**.
7373

@@ -113,18 +113,24 @@ Full schemas and examples: **<a href="docs/API.md">docs/API.md</a>**
113113

114114
## Rules Engine
115115

116-
Drop a TypeScript file in `rules/` and bounty-bot loads it at startup. Each file exports an array of typed rules that are evaluated during the pipeline and injected into the LLM prompt.
116+
Two kinds of rules, two directories:
117117

118118
```
119119
rules/
120-
validity.ts # body length, title quality, structure
121-
media.ts # evidence requirements
122-
spam.ts # template detection, generic titles
123-
content.ts # profanity, length limits, context
124-
scoring.ts # penalty weight adjustments
120+
code/ # Programmatic checks — executed by the engine
121+
validity.ts # body length, title quality, structure
122+
media.ts # evidence requirements
123+
spam.ts # template detection, generic titles
124+
content.ts # profanity, length limits, context
125+
scoring.ts # penalty weight adjustments
126+
llm/ # LLM instructions — injected into the prompt
127+
evaluation.ts # evidence priority, reproducibility, confidence
128+
tone.ts # professional tone, no sympathy verdicts
129+
spam-detection.ts # template farming, AI filler, screenshot mismatch
130+
output-format.ts # tool usage, reasoning order, no internal leaks
125131
```
126132

127-
Four severity levels:
133+
**Code rules** run programmatically and produce pass/fail results. They short-circuit the pipeline:
128134

129135
| Severity | Effect |
130136
|---|---|
@@ -133,6 +139,8 @@ Four severity levels:
133139
| `penalize` | Adds weight to penalty score |
134140
| `flag` | Logged but no verdict change |
135141

142+
**LLM rules** are natural-language instructions injected into the model's system prompt, ordered by priority (`critical` > `high` > `normal` > `low`). They shape how the model reasons and phrases its verdict.
143+
136144
Hot-reload without restart: `POST /api/v1/rules/reload`
137145

138146
Full documentation: **<a href="docs/RULES.md">docs/RULES.md</a>**

0 commit comments

Comments
 (0)