@albinocrabs/feynman 0.2.0 → 0.2.2
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/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +10 -0
- package/CONTRIBUTING.md +126 -0
- package/README.md +22 -4
- package/SECURITY.md +31 -0
- package/bin/feynman.js +5 -5
- package/docs/architecture.md +190 -0
- package/docs/launch.md +67 -0
- package/docs/lint-rules.md +317 -0
- package/docs/self-improvement.md +281 -0
- package/docs/visual-patterns.md +253 -0
- package/examples/algorithm-explain.md +70 -0
- package/examples/api-flow.md +55 -0
- package/examples/architecture-review.md +50 -0
- package/examples/code-review.md +55 -0
- package/examples/db-schema.md +48 -0
- package/examples/deploy-pipeline.md +58 -0
- package/package.json +13 -3
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# Lint Rules Reference
|
|
2
|
+
|
|
3
|
+
feynman includes a linter for ASCII diagrams in markdown files.
|
|
4
|
+
Eight rules (L01-L08) enforce structural correctness.
|
|
5
|
+
|
|
6
|
+
Run: `npx @albinocrabs/feynman lint <file.md>` or `feynman lint <file.md>`
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## L01: Box Closure (severity: error)
|
|
11
|
+
|
|
12
|
+
**What:** Every `┌` corner must have a matching `└` at the same column position;
|
|
13
|
+
every `┐` must have a matching `┘` at the same column.
|
|
14
|
+
|
|
15
|
+
**Why:** An unclosed frame box is visually deceptive — it implies containment
|
|
16
|
+
it doesn't deliver, and the unclosed edge is often invisible at a glance.
|
|
17
|
+
|
|
18
|
+
**Source:** [`lib/lint/rules.js#L66`](../lib/lint/rules.js)
|
|
19
|
+
|
|
20
|
+
### Valid
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
┌─ Status ──────┐
|
|
24
|
+
│ item-a done │
|
|
25
|
+
│ item-b wait │
|
|
26
|
+
└───────────────┘
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Invalid
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
┌─ Status ─────────────┐
|
|
33
|
+
│ item-a done │
|
|
34
|
+
│ item-b in progress│
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Output:
|
|
38
|
+
```text
|
|
39
|
+
file:2:1: L01 Unclosed box: '┌' at line 2, col 1 has no matching '└' at same column
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## L02: Tree Chars (severity: error)
|
|
45
|
+
|
|
46
|
+
**What:** The last child in each group of siblings must use `└──`, not `├──`.
|
|
47
|
+
|
|
48
|
+
**Why:** `├──` means "more siblings follow"; `└──` means "last child." Using
|
|
49
|
+
`├──` for the last item misleads the reader about the list's structure.
|
|
50
|
+
|
|
51
|
+
**Source:** [`lib/lint/rules.js#L156`](../lib/lint/rules.js)
|
|
52
|
+
|
|
53
|
+
### Valid
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
project
|
|
57
|
+
├── src
|
|
58
|
+
│ ├── components
|
|
59
|
+
│ └── utils
|
|
60
|
+
└── package.json
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Invalid
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
project
|
|
67
|
+
├── src
|
|
68
|
+
│ ├── components
|
|
69
|
+
│ ├── utils
|
|
70
|
+
├── tests
|
|
71
|
+
├── package.json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Output:
|
|
75
|
+
```text
|
|
76
|
+
file:6:1: L02 Last tree child uses '├──' but should use '└──'
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## L03: Arrow Style (severity: error)
|
|
82
|
+
|
|
83
|
+
**What:** Only one arrow style is allowed per diagram.
|
|
84
|
+
|
|
85
|
+
Recognized styles:
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
→
|
|
89
|
+
-->
|
|
90
|
+
─→
|
|
91
|
+
──>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Why:** Mixed arrow styles force the reader to verify that the styles are
|
|
95
|
+
equivalent rather than distinct, adding cognitive overhead without information.
|
|
96
|
+
|
|
97
|
+
**Source:** [`lib/lint/rules.js#L227`](../lib/lint/rules.js)
|
|
98
|
+
|
|
99
|
+
### Valid
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
[Step A] --> [Step B] --> [Step C]
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Invalid
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
[Step A] --> [Step B] → [Step C] --> [Step D]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Output:
|
|
112
|
+
```text
|
|
113
|
+
file:1:1: L03 Mixed arrow styles: diagram uses '-->' and '→' — pick one style
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## L04: Column Widths (severity: error)
|
|
119
|
+
|
|
120
|
+
**What:** All rows in a markdown table must have the same column count.
|
|
121
|
+
The separator row (`|---|---|`) must match the header column count.
|
|
122
|
+
|
|
123
|
+
**Why:** Mismatched column counts break the visual grid — the reader must
|
|
124
|
+
count pipes instead of reading structure.
|
|
125
|
+
|
|
126
|
+
**Source:** [`lib/lint/rules.js#L272`](../lib/lint/rules.js)
|
|
127
|
+
|
|
128
|
+
### Valid
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
Option A | Option B | Option C
|
|
132
|
+
------------|-------------|----------
|
|
133
|
+
fast | slow | medium
|
|
134
|
+
stateless | persistent | persistent
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Invalid
|
|
138
|
+
|
|
139
|
+
```text
|
|
140
|
+
Option A | Option B
|
|
141
|
+
------------|-------------|----------
|
|
142
|
+
fast | slow | medium
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Output:
|
|
146
|
+
```text
|
|
147
|
+
file:2:1: L04 Table separator has 3 columns but header has 2 columns
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## L05: Flow Integrity (severity: error)
|
|
153
|
+
|
|
154
|
+
**What:** When two or more `[Box]` tokens appear on the same line, an arrow
|
|
155
|
+
must exist between each consecutive pair.
|
|
156
|
+
|
|
157
|
+
**Why:** Adjacent boxes without arrows are ambiguous — are they sequential
|
|
158
|
+
steps, parallel options, or unrelated elements? An arrow makes the
|
|
159
|
+
relationship explicit.
|
|
160
|
+
|
|
161
|
+
**Source:** [`lib/lint/rules.js#L349`](../lib/lint/rules.js)
|
|
162
|
+
|
|
163
|
+
Note: boxes separated by three or more spaces are treated as parallel layout
|
|
164
|
+
(e.g. side-by-side comparison columns) and do not require an arrow.
|
|
165
|
+
|
|
166
|
+
### Valid
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
[Auth] --> [Handler] --> [Response]
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Invalid
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
[Auth] [Handler] [Response]
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Output:
|
|
179
|
+
```text
|
|
180
|
+
file:1:1: L05 3 boxes on same line with no arrow between them: [Auth], [Handler], [Response]
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## L06: Priority Scale (severity: warn)
|
|
186
|
+
|
|
187
|
+
**What:** When `▲` appears in a diagram, `▼` must also appear, and vice versa.
|
|
188
|
+
|
|
189
|
+
**Why:** A priority scale with only one end is not a scale — the reader
|
|
190
|
+
cannot determine whether the listed items are near the top or bottom of
|
|
191
|
+
the full range.
|
|
192
|
+
|
|
193
|
+
**Source:** [`lib/lint/rules.js#L399`](../lib/lint/rules.js)
|
|
194
|
+
|
|
195
|
+
### Valid
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
▲ high
|
|
199
|
+
critical-bug
|
|
200
|
+
security-patch
|
|
201
|
+
▼ low
|
|
202
|
+
cosmetic-fix
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Invalid
|
|
206
|
+
|
|
207
|
+
```text
|
|
208
|
+
▲ high
|
|
209
|
+
critical-bug
|
|
210
|
+
security-patch
|
|
211
|
+
performance-fix
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Output:
|
|
215
|
+
```text
|
|
216
|
+
file:1:1: L06 Priority scale has '▲' but missing '▼' — scales require both ends
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## L07: No Mermaid + ASCII Mix (severity: warn)
|
|
222
|
+
|
|
223
|
+
**What:** A document must not contain both a Mermaid fenced block and ASCII
|
|
224
|
+
diagram characters such as box corners, arrows, or tree branches.
|
|
225
|
+
|
|
226
|
+
**Why:** Mixing two diagram encoding systems forces the reader to context-switch
|
|
227
|
+
between visual vocabularies. It also signals that the response lacks a coherent
|
|
228
|
+
visual strategy.
|
|
229
|
+
|
|
230
|
+
**Source:** [`lib/lint/rules.js#L441`](../lib/lint/rules.js)
|
|
231
|
+
|
|
232
|
+
### Valid
|
|
233
|
+
|
|
234
|
+
A file with only ASCII diagrams:
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
[A] --> [B] --> [C]
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Invalid
|
|
241
|
+
|
|
242
|
+
A file with both a Mermaid block and ASCII art (shown as `text` fences to
|
|
243
|
+
avoid triggering the rule):
|
|
244
|
+
|
|
245
|
+
```text
|
|
246
|
+
[A] --> [B]
|
|
247
|
+
|
|
248
|
+
` ``mermaid
|
|
249
|
+
graph TD
|
|
250
|
+
A --> B
|
|
251
|
+
` ``
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Output:
|
|
255
|
+
```text
|
|
256
|
+
file:4:1: L07 Response mixes Mermaid (line 4) and ASCII diagrams — use one format only
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## L08: Frame Width Discipline (severity: error)
|
|
262
|
+
|
|
263
|
+
**What:** All rows inside a `┌─ … ─┐` frame block must have the same
|
|
264
|
+
display width (measured in terminal columns).
|
|
265
|
+
|
|
266
|
+
**Why:** Ragged right edges in a frame add visual noise without information.
|
|
267
|
+
Consistent width makes the frame a clean visual container.
|
|
268
|
+
|
|
269
|
+
**Source:** [`lib/lint/rules.js#L476`](../lib/lint/rules.js)
|
|
270
|
+
|
|
271
|
+
Display width counts each Unicode character as 1 column (box-drawing
|
|
272
|
+
characters, Latin, and Cyrillic are single-width; CJK characters are
|
|
273
|
+
double-width).
|
|
274
|
+
|
|
275
|
+
### Valid
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
┌─ Status ──────┐
|
|
279
|
+
│ item-a done │
|
|
280
|
+
│ item-b wait │
|
|
281
|
+
│ item-c ok │
|
|
282
|
+
└───────────────┘
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Invalid
|
|
286
|
+
|
|
287
|
+
```text
|
|
288
|
+
┌─ Status ─────┐
|
|
289
|
+
│ item-a done │
|
|
290
|
+
│ item-b in progress - this line is much wider than the frame header
|
|
291
|
+
└─────────────────────────────┘
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Output:
|
|
295
|
+
```text
|
|
296
|
+
file:3:1: L08 Frame row width 68 differs from frame header width 16 (line 1)
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## `language: text` Convention
|
|
302
|
+
|
|
303
|
+
To include intentionally-invalid diagram examples in documentation (as this
|
|
304
|
+
file does), wrap them in fences with the `text` language tag:
|
|
305
|
+
|
|
306
|
+
````markdown
|
|
307
|
+
```text
|
|
308
|
+
[A] [B] ← no arrow — intentionally invalid for L05
|
|
309
|
+
```
|
|
310
|
+
````
|
|
311
|
+
|
|
312
|
+
The parser recognizes fenced code blocks but only lints blocks with no
|
|
313
|
+
language tag or with diagram-relevant languages. Blocks tagged `text` are
|
|
314
|
+
skipped.
|
|
315
|
+
|
|
316
|
+
This is the recommended way to document "bad" examples without causing
|
|
317
|
+
lint failures in your documentation files.
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# Self-Improvement Loop Design
|
|
2
|
+
|
|
3
|
+
This document designs a future feedback loop for feynman rules. It is a
|
|
4
|
+
research spec only. Implementation is deferred to v0.3.0 under BENCH-V3-02.
|
|
5
|
+
|
|
6
|
+
The goal is not automatic rule rewriting. The goal is a reviewable trail from
|
|
7
|
+
lint failures to human-approved rule changes.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Scope
|
|
12
|
+
|
|
13
|
+
In scope:
|
|
14
|
+
|
|
15
|
+
- Failure log schema for `feynman-lint`
|
|
16
|
+
- Aggregation step for recurring failures
|
|
17
|
+
- Rule-update proposal format
|
|
18
|
+
- Human review gate
|
|
19
|
+
- Rollout cadence
|
|
20
|
+
- Kill-switch
|
|
21
|
+
- Open questions for v0.3.0
|
|
22
|
+
|
|
23
|
+
Out of scope:
|
|
24
|
+
|
|
25
|
+
- Automatic edits to `rules/feynman-activate.md`
|
|
26
|
+
- Telemetry upload or remote collection
|
|
27
|
+
- Background daemon
|
|
28
|
+
- Model-generated pull requests
|
|
29
|
+
- Per-user analytics dashboard
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Loop Overview
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
[Claude response] --> [feynman-lint]
|
|
37
|
+
|
|
|
38
|
+
pass + fail
|
|
39
|
+
| |
|
|
40
|
+
v v
|
|
41
|
+
[silent] [local failure log]
|
|
42
|
+
|
|
|
43
|
+
v
|
|
44
|
+
[aggregate patterns]
|
|
45
|
+
|
|
|
46
|
+
v
|
|
47
|
+
[proposal file]
|
|
48
|
+
|
|
|
49
|
+
v
|
|
50
|
+
[human review]
|
|
51
|
+
|
|
|
52
|
+
accept + reject
|
|
53
|
+
| |
|
|
54
|
+
v v
|
|
55
|
+
[rule PR] [archive reason]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The loop stays local-first. A user can inspect every captured failure before
|
|
59
|
+
anything affects rules.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Failure Log Schema
|
|
64
|
+
|
|
65
|
+
Each failed lint run writes one JSONL row. The path is proposed for v0.3.0:
|
|
66
|
+
`~/.claude/.feynman/failures.jsonl`.
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"schema": 1,
|
|
71
|
+
"timestamp": "2026-05-06T21:10:00Z",
|
|
72
|
+
"feynmanVersion": "0.2.0",
|
|
73
|
+
"source": "stop-hook",
|
|
74
|
+
"rulesetIntensity": "full",
|
|
75
|
+
"documentHash": "sha256:...",
|
|
76
|
+
"issues": [
|
|
77
|
+
{
|
|
78
|
+
"rule": "L05",
|
|
79
|
+
"severity": "error",
|
|
80
|
+
"line": 12,
|
|
81
|
+
"column": 1,
|
|
82
|
+
"message": "2 boxes on same line with no arrow between them",
|
|
83
|
+
"diagramShape": "flow",
|
|
84
|
+
"snippetHash": "sha256:..."
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"context": {
|
|
88
|
+
"fileKind": "response",
|
|
89
|
+
"hasCodeFence": true,
|
|
90
|
+
"diagramChars": 42,
|
|
91
|
+
"lineCount": 9
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Privacy rule: raw response text is not logged by default. Hashes and structural
|
|
97
|
+
metadata are enough to find repeated failure patterns without storing content.
|
|
98
|
+
|
|
99
|
+
Optional debug mode can store redacted snippets, but only behind an explicit
|
|
100
|
+
local config flag.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Aggregation Step
|
|
105
|
+
|
|
106
|
+
Aggregation groups failures by rule, diagram shape, and structural signature.
|
|
107
|
+
It runs manually, not in the hook path.
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
[failures.jsonl]
|
|
111
|
+
|
|
|
112
|
+
v
|
|
113
|
+
[group by rule + shape + signature]
|
|
114
|
+
|
|
|
115
|
+
v
|
|
116
|
+
[rank by frequency + recency + severity]
|
|
117
|
+
|
|
|
118
|
+
v
|
|
119
|
+
[candidate patterns]
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Candidate score:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
score = (error_count * 3) + warn_count + recent_count - ignored_count
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Aggregation output is a local markdown report:
|
|
129
|
+
`~/.claude/.feynman/proposals/YYYY-MM.md`.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Rule-Update Proposal Format
|
|
134
|
+
|
|
135
|
+
Each proposal must be small enough for review in one PR.
|
|
136
|
+
|
|
137
|
+
```markdown
|
|
138
|
+
# Proposal: tighten L05 flow spacing guidance
|
|
139
|
+
|
|
140
|
+
## Trigger
|
|
141
|
+
|
|
142
|
+
- Rule: L05
|
|
143
|
+
- Pattern: parallel boxes with one or two spaces
|
|
144
|
+
- Count: 18 failures in 30 days
|
|
145
|
+
|
|
146
|
+
## Evidence
|
|
147
|
+
|
|
148
|
+
- Structural signature: multibox_same_line_no_arrow
|
|
149
|
+
- Common shape: branch output rows
|
|
150
|
+
- Existing docs affected: examples/api-flow.md, examples/deploy-pipeline.md
|
|
151
|
+
|
|
152
|
+
## Proposed Rule Change
|
|
153
|
+
|
|
154
|
+
Change prose in `rules/feynman-activate.md` to state that side-by-side
|
|
155
|
+
parallel boxes use three or more spaces.
|
|
156
|
+
|
|
157
|
+
## Test Plan
|
|
158
|
+
|
|
159
|
+
- Add one valid fixture for parallel layout
|
|
160
|
+
- Add one invalid fixture for adjacent boxes
|
|
161
|
+
- Run `npm test`
|
|
162
|
+
- Run `feynman-lint` over docs/examples
|
|
163
|
+
|
|
164
|
+
## Rollout
|
|
165
|
+
|
|
166
|
+
- Merge behind normal release process
|
|
167
|
+
- Mention in changelog
|
|
168
|
+
- No runtime migration
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Proposal files are advisory. They do not modify rules by themselves.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Human Review Gate
|
|
176
|
+
|
|
177
|
+
Every proposal goes through a maintainer decision.
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
[proposal]
|
|
181
|
+
|
|
|
182
|
+
v
|
|
183
|
+
[maintainer review]
|
|
184
|
+
|
|
|
185
|
+
+--> [accept] --> [normal PR]
|
|
186
|
+
|
|
|
187
|
+
+--> [revise] --> [proposal update]
|
|
188
|
+
|
|
|
189
|
+
+--> [reject] --> [archive with reason]
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Review checklist:
|
|
193
|
+
|
|
194
|
+
- Does the failure repeat across multiple prompts or files?
|
|
195
|
+
- Is the current rule actually wrong, or is the diagram wrong?
|
|
196
|
+
- Would the rule change increase unwanted diagrams?
|
|
197
|
+
- Does it preserve declarative phrasing?
|
|
198
|
+
- Does it keep the rule block under the size cap?
|
|
199
|
+
- Does it add or update golden tests?
|
|
200
|
+
|
|
201
|
+
No proposal is accepted without tests and docs/examples self-lint.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Rollout Cadence
|
|
206
|
+
|
|
207
|
+
Recommended cadence for v0.3.0:
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
weekly collect local failures, no action
|
|
211
|
+
monthly generate proposal report
|
|
212
|
+
release merge accepted rule changes
|
|
213
|
+
hotfix only for false positives that block normal use
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Rule changes should batch by release unless a linter bug causes high-noise
|
|
217
|
+
false positives.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Kill-Switch
|
|
222
|
+
|
|
223
|
+
The loop needs a hard local off switch before implementation.
|
|
224
|
+
|
|
225
|
+
Proposed config:
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"selfImprovement": {
|
|
230
|
+
"enabled": false,
|
|
231
|
+
"logFailures": false,
|
|
232
|
+
"storeSnippets": false,
|
|
233
|
+
"proposalCadence": "manual"
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Default is off. If enabled, logging remains local. If disabled, the Stop hook
|
|
239
|
+
does not write failure logs.
|
|
240
|
+
|
|
241
|
+
Emergency behavior:
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
[selfImprovement.enabled=false] --> [no logs]
|
|
245
|
+
[logFailures=false] --> [no logs]
|
|
246
|
+
[corrupt config] --> [fail closed: no logs]
|
|
247
|
+
[write error] --> [silent; never block Claude]
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The hook must never fail a user prompt because logging failed.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Data Retention
|
|
255
|
+
|
|
256
|
+
Suggested defaults:
|
|
257
|
+
|
|
258
|
+
- Keep aggregate reports until deleted by user.
|
|
259
|
+
- Keep raw JSONL failure rows for 30 days.
|
|
260
|
+
- Never write raw response text unless debug mode is explicitly enabled.
|
|
261
|
+
- Provide `feynman self-improve purge` in v0.3.0 if the feature ships.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Open Questions
|
|
266
|
+
|
|
267
|
+
- Should this live behind `feynman doctor` checks or a separate subcommand?
|
|
268
|
+
- Should proposal generation be part of `feynman lint --report`?
|
|
269
|
+
- Should snippet redaction exist, or should raw snippets be disallowed entirely?
|
|
270
|
+
- How should proposal scores account for false positives fixed in the same
|
|
271
|
+
release?
|
|
272
|
+
- Should team-level aggregation exist, or is local-only the permanent boundary?
|
|
273
|
+
- Can rule proposals remain useful without storing prompt context?
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Deferred Implementation
|
|
278
|
+
|
|
279
|
+
Implementation is explicitly deferred to v0.3.0 (BENCH-V3-02). v0.2.0 ships
|
|
280
|
+
only this design document. No runtime code, CLI command, hook behavior, config
|
|
281
|
+
schema, or logging path is added in this milestone.
|