@albinocrabs/feynman 0.2.0 → 0.2.1

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.
@@ -0,0 +1,253 @@
1
+ # Visual Patterns: Research Foundation
2
+
3
+ How feynman's rules derive from visual communication research.
4
+
5
+ ---
6
+
7
+ ## Core Principle
8
+
9
+ A diagram should reduce the cognitive work required to extract information.
10
+ When prose describes a structure, the reader must reconstruct that structure
11
+ mentally. A diagram presents the structure directly.
12
+
13
+ feynman operationalizes this principle in eight lint rules (L01-L08) that
14
+ enforce correctness of the most common ASCII diagram patterns.
15
+
16
+ ---
17
+
18
+ ## Tufte: Data-Ink Ratio
19
+
20
+ **Source:** Edward R. Tufte, *The Visual Display of Quantitative Information*, 2nd ed.
21
+ Graphics Press, 2001.
22
+
23
+ Tufte's central rule: maximize the ratio of data ink to total ink. Remove
24
+ everything that does not carry information.
25
+
26
+ ```
27
+ data-ink ratio = (ink carrying data) / (total ink in graphic)
28
+
29
+ high ratio --> dense, clear
30
+ low ratio --> cluttered, noisy
31
+ ```
32
+
33
+ **Small multiples** (Tufte, *Envisioning Information*, 1990) — repeat the same
34
+ graphic structure across multiple instances to enable comparison. The same
35
+ visual encoding applied consistently lets the eye detect differences without
36
+ re-learning the encoding.
37
+
38
+ ### How feynman embodies Tufte
39
+
40
+ **L08 frame width discipline** directly enforces data-ink ratio in ASCII frames.
41
+ Every row in a frame block must have the same display width. Ragged right
42
+ edges add visual noise without information.
43
+
44
+ Valid (consistent width — passes L08):
45
+
46
+ ```
47
+ ┌─ Status ──────┐
48
+ │ item-a ok │
49
+ │ item-b wait │
50
+ └───────────────┘
51
+ ```
52
+
53
+ Invalid (ragged right edge — fails L08):
54
+
55
+ ```text
56
+ ┌─ Status ─────┐
57
+ │ item-a done │
58
+ │ item-b in progress│
59
+ └────────┘
60
+ ```
61
+
62
+ **L01 box closure** enforces structural completeness. An unclosed box is
63
+ decoration without information — the visual boundary promises containment
64
+ but does not deliver it.
65
+
66
+ ---
67
+
68
+ ## Few: Pre-Attentive Attributes
69
+
70
+ **Source:** Stephen Few, *Show Me the Numbers*, 2nd ed. Analytics Press, 2012.
71
+ Stephen Few, *Now You See It*. Analytics Press, 2009.
72
+
73
+ Pre-attentive processing happens in under 250 ms, before conscious attention.
74
+ Attributes processed pre-attentively include: position, length, size, color,
75
+ orientation, shape, and enclosure.
76
+
77
+ For ASCII diagrams, the relevant pre-attentive attributes are:
78
+
79
+ ```
80
+ attribute | ASCII representation | activates
81
+ -------------|-----------------------------|--------------------------
82
+ position | indentation, left-alignment | hierarchy, sequence
83
+ enclosure | frame blocks | grouping
84
+ shape | [box] vs tree vs lines | diagram type
85
+ orientation | --> (horizontal) vs | | flow direction
86
+ ```
87
+
88
+ Few's dashboard principle: a viewer should be able to identify the most
89
+ important item within 5 seconds. In a code review response, `▲` and `▼`
90
+ markers make the highest and lowest priority items instantly findable.
91
+
92
+ ### How feynman embodies Few
93
+
94
+ **L06 priority scale** enforces that `▲` and `▼` always appear together.
95
+ A scale with only one end is not a scale — it lacks the reference point
96
+ that makes the pre-attentive contrast useful.
97
+
98
+ Valid (both ends — passes L06):
99
+
100
+ ```
101
+ ▲ high
102
+ critical-bug
103
+ security-patch
104
+ ▼ low
105
+ cosmetic-fix
106
+ ```
107
+
108
+ Invalid (one end only — fails L06):
109
+
110
+ ```text
111
+ ▲ high
112
+ critical-bug
113
+ security-patch
114
+ ```
115
+
116
+ Without `▼ low`, the reader cannot determine whether "security-patch" is at
117
+ the top, middle, or bottom of the full severity range.
118
+
119
+ **L05 flow integrity** enforces that boxes in sequence have arrows between them.
120
+ The pre-attentive attribute of position implies connection only when supported
121
+ by an explicit visual link. Two boxes next to each other with no arrow are
122
+ ambiguous — parallel? sequential? unrelated?
123
+
124
+ ---
125
+
126
+ ## Bertin: Visual Variables
127
+
128
+ **Source:** Jacques Bertin, *Semiology of Graphics*, trans. William J. Berg.
129
+ University of Wisconsin Press, 1983 (orig. 1967).
130
+
131
+ Bertin identified seven visual variables: position, size, value (lightness),
132
+ texture, color, orientation, and shape. Each variable has different
133
+ *retinal properties* — they vary in whether they communicate order, quantity,
134
+ or mere difference.
135
+
136
+ For monochrome ASCII (no color, no size variation), the available variables are:
137
+
138
+ ```
139
+ variable | ASCII encoding | retinal property
140
+ -------------|─────────────────────────────────|------------------
141
+ position | column, indentation level | order, quantity
142
+ orientation | --> (horizontal) | (vertical) | difference
143
+ shape | frame vs [box] vs tree vs scale | difference
144
+ texture | - vs space vs | fill | difference
145
+ ```
146
+
147
+ Bertin's key insight: variables must be used consistently within a graphic.
148
+ Inconsistent use of a variable adds noise without information.
149
+
150
+ ### How feynman embodies Bertin
151
+
152
+ **L02 tree chars** enforces consistent use of the shape variable.
153
+ In ASCII trees, `├──` signals "more siblings follow" and `└──` signals
154
+ "last sibling." Using `├──` for the last child violates Bertin's consistency
155
+ requirement — the shape variable now carries conflicting information.
156
+
157
+ Valid (correct last-child marker — passes L02):
158
+
159
+ ```
160
+ root
161
+ ├── child-a
162
+ ├── child-b
163
+ └── child-c
164
+ ```
165
+
166
+ Invalid (wrong last-child marker — fails L02):
167
+
168
+ ```text
169
+ root
170
+ ├── child-a
171
+ ├── child-b
172
+ ├── child-c
173
+ ```
174
+
175
+ **L03 arrow style** enforces consistency of the shape variable for directional
176
+ links. `-->`, `─→`, and `──>` all encode "directed connection," but mixing
177
+ them within a single diagram adds visual noise. The reader must expend
178
+ attention verifying that mixed styles are equivalent rather than distinct.
179
+
180
+ Valid (consistent style — passes L03):
181
+
182
+ ```
183
+ [A] --> [B] --> [C] --> [D]
184
+ ```
185
+
186
+ Invalid (mixed styles — fails L03):
187
+
188
+ ```text
189
+ [A] --> [B] --> [C] --> [D]
190
+ ```
191
+
192
+ Note: the invalid example above only becomes invalid when `→` appears alongside
193
+ `-->` in the same diagram block.
194
+
195
+ **L04 column widths** enforces consistent position encoding in tables.
196
+ Misaligned column separators break the visual grid — the position variable
197
+ now encodes nothing, forcing the reader to count pipes instead of reading
198
+ structure.
199
+
200
+ ---
201
+
202
+ ## Knaflic: Annotation and Focus
203
+
204
+ **Source:** Cole Nussbaumer Knaflic, *Storytelling with Data*. Wiley, 2015.
205
+
206
+ Knaflic emphasizes that every visual element should serve a purpose, and that
207
+ annotation should guide attention to what matters. Unlabeled structures leave
208
+ the reader to infer the author's intent.
209
+
210
+ **L07 no mermaid/ASCII mix** enforces a single visual vocabulary per document.
211
+ Mixing Mermaid syntax and ASCII diagrams forces the reader to context-switch
212
+ between two encoding systems. It also signals that the response was assembled
213
+ without a deliberate visual strategy.
214
+
215
+ ---
216
+
217
+ ## Principle-to-Rule Mapping
218
+
219
+ ```
220
+ principle | rule | what it enforces
221
+ ------------------------------|------|---------------------------------------------
222
+ Tufte: data-ink ratio | L08 | frame rows same width (no wasted ink)
223
+ Tufte: structural completeness| L01 | every box-open has a matching box-close
224
+ Few: pre-attentive scale | L06 | both scale ends (▲ and ▼) always present
225
+ Few: position implies sequence| L05 | boxes in sequence require explicit arrows
226
+ Bertin: shape consistency | L02 | last tree child uses └── not ├──
227
+ Bertin: shape consistency | L03 | one arrow style per diagram
228
+ Bertin: position encoding | L04 | table column counts consistent across rows
229
+ Knaflic: single vocabulary | L07 | no mermaid + ASCII mix in same document
230
+ ```
231
+
232
+ ---
233
+
234
+ ## Bibliography
235
+
236
+ - Tufte, Edward R. *The Visual Display of Quantitative Information*, 2nd ed.
237
+ Cheshire, CT: Graphics Press, 2001.
238
+
239
+ - Tufte, Edward R. *Envisioning Information*. Cheshire, CT: Graphics Press,
240
+ 1990.
241
+
242
+ - Few, Stephen. *Show Me the Numbers: Designing Tables and Graphs to Enlighten*,
243
+ 2nd ed. Burlingame, CA: Analytics Press, 2012.
244
+
245
+ - Few, Stephen. *Now You See It: Simple Visualization Techniques for Quantitative
246
+ Analysis*. Burlingame, CA: Analytics Press, 2009.
247
+
248
+ - Bertin, Jacques. *Semiology of Graphics: Diagrams, Networks, Maps*. Trans.
249
+ William J. Berg. Madison, WI: University of Wisconsin Press, 1983.
250
+ (Original: *Semiologie graphique*, Gauthier-Villars, 1967.)
251
+
252
+ - Nussbaumer Knaflic, Cole. *Storytelling with Data: A Data Visualization
253
+ Guide for Business Professionals*. Hoboken, NJ: Wiley, 2015.
@@ -0,0 +1,70 @@
1
+ # Algorithm: Token-Bucket Rate Limiter
2
+
3
+ ## Question
4
+
5
+ > Explain how a token-bucket rate limiter works. Walk through the state
6
+ > machine and the per-request decision logic.
7
+
8
+ ## Without feynman
9
+
10
+ A token bucket holds up to N tokens. Tokens are added at a fixed rate (the
11
+ refill rate). When a request arrives, one token is consumed. If the bucket
12
+ is empty the request is rejected. Over time the bucket refills up to its
13
+ capacity. Bursts are handled because a full bucket allows N requests
14
+ immediately; sustained overload is prevented because refill is bounded.
15
+
16
+ ## With feynman
17
+
18
+ State machine:
19
+
20
+ ```
21
+ [bucket: N tokens]
22
+ |
23
+ +-- tick (every 1/rate seconds)
24
+ | |
25
+ | v
26
+ | [add 1 token, cap at N]
27
+ |
28
+ +-- request arrives
29
+ |
30
+ v
31
+ [check bucket]
32
+ |
33
+ empty -+- has token
34
+ | |
35
+ v v
36
+ [reject 429] [tokens--]
37
+ |
38
+ v
39
+ [allow request]
40
+ ```
41
+
42
+ Per-request decision flow:
43
+
44
+ ```
45
+ [request] --> [read bucket state] --> [tokens > 0?]
46
+ |
47
+ yes -----+------ no
48
+ | |
49
+ v v
50
+ [tokens--] [reject 429]
51
+ [allow] [retry-after]
52
+ ```
53
+
54
+ Key properties:
55
+
56
+ ```
57
+ property | value
58
+ -----------------|----------------------------------
59
+ burst capacity | N tokens (full bucket)
60
+ sustained rate | refill rate (tokens/second)
61
+ penalty | token consumed even on error
62
+ state storage | counter + last_refill timestamp
63
+ ```
64
+
65
+ ## Why this works
66
+
67
+ An algorithm with internal states and per-step decisions maps to feynman's
68
+ flow-diagram rule. The state diagram shows the two concurrent processes
69
+ (tick refill and request consume); the flow diagram shows per-request
70
+ branching; the table captures the rate-limit contract in comparable columns.
@@ -0,0 +1,55 @@
1
+ # API Flow: POST /api/login Request Lifecycle
2
+
3
+ ## Question
4
+
5
+ > Walk me through exactly what happens when a client sends POST /api/login.
6
+ > Include middleware, validation, and the response path.
7
+
8
+ ## Without feynman
9
+
10
+ When a login request arrives the framework runs the CORS middleware first,
11
+ then body-parser parses the JSON payload. The validation layer checks that
12
+ email and password fields are present and well-formed. The controller calls
13
+ the auth service, which queries the database. If credentials match, a session
14
+ token is issued and returned. If anything fails along the way an appropriate
15
+ error response is sent.
16
+
17
+ ## With feynman
18
+
19
+ ```
20
+ [Client] --> [CORS middleware] --> [body-parser] --> [Validation]
21
+ |
22
+ pass --+-- fail
23
+ | |
24
+ v v
25
+ [Controller] [400 Bad Request]
26
+ |
27
+ v
28
+ [AuthService]
29
+ |
30
+ v
31
+ [UserRepository]
32
+ |
33
+ found ----+---- not found
34
+ | |
35
+ v v
36
+ bcrypt.compare [401 Unauthorized]
37
+ |
38
+ match --+-- mismatch
39
+ | |
40
+ v v
41
+ [issue JWT] [401 Unauthorized]
42
+ |
43
+ v
44
+ [200 OK + token]
45
+ ```
46
+
47
+ Seven stages, two branch points. Every failure path exits early — success
48
+ continues to the next stage.
49
+
50
+ ## Why this works
51
+
52
+ The request lifecycle is a sequential flow with conditional branches, which
53
+ activates feynman's flow diagram rules. Boxes (`[…]`) mark processing stages;
54
+ arrows (`-->`) mark data flow; branch splits show the conditional paths at
55
+ validation and credential-check points.
@@ -0,0 +1,50 @@
1
+ # Architecture Review: Auth Service Topology
2
+
3
+ ## Question
4
+
5
+ > How does our auth service connect to the user database and rate limiter?
6
+ > Walk me through the request path.
7
+
8
+ ## Without feynman
9
+
10
+ The auth service receives incoming requests and first checks the rate limiter
11
+ to see if the caller has exceeded their quota. If not, it queries the user
12
+ database to validate credentials. On success it issues a JWT and logs the
13
+ event. If the rate limiter trips, the request is rejected before the database
14
+ is ever touched.
15
+
16
+ ## With feynman
17
+
18
+ ```
19
+ [POST /auth/token]
20
+ |
21
+ v
22
+ [Rate Limiter: Redis, 100 req/60s per IP]
23
+ |
24
+ over limit --> 429 Too Many Requests
25
+ |
26
+ within limit
27
+ |
28
+ v
29
+ [Auth Service: validate credentials]
30
+ |
31
+ v
32
+ [UserDB: SELECT hash WHERE email = ?]
33
+ |
34
+ v
35
+ [bcrypt.compare(password, hash)]
36
+ |
37
+ match --> issue JWT (RS256, 15 min TTL) --> 200 OK
38
+ |
39
+ no match --> 401 Unauthorized
40
+ ```
41
+
42
+ Three components, one path. Rate limiter sits in front — database never sees
43
+ throttled traffic.
44
+
45
+ ## Why this works
46
+
47
+ The response describes a hierarchy of sequential components with decision
48
+ branches, activating feynman's flow-integrity and frame-block rules. The flow
49
+ diagram shows each processing stage as a box with arrows marking the request
50
+ path and branch outcomes.
@@ -0,0 +1,55 @@
1
+ # Code Review: PR with Mixed-Severity Issues
2
+
3
+ ## Question
4
+
5
+ > Review this PR. It has a SQL injection vulnerability in the login handler,
6
+ > a missing null check that could cause crashes, and a variable name that
7
+ > doesn't follow conventions. How should I prioritize the fixes?
8
+
9
+ ## Without feynman
10
+
11
+ The SQL injection is the most critical issue because it's a security
12
+ vulnerability that could expose user data. The missing null check is serious
13
+ because it causes crashes in production but doesn't expose data. The naming
14
+ convention issue is low severity — it's cosmetic and only affects readability.
15
+ Fix security first, stability second, style last.
16
+
17
+ ## With feynman
18
+
19
+ Priority order:
20
+
21
+ ```
22
+ ▲ high
23
+ SQL injection (login handler, line 47)
24
+ — user input concatenated into query string
25
+ — fix: parameterized query or ORM method
26
+
27
+ null check missing (user.profile access, line 83)
28
+ — crashes when user has no profile row
29
+ — fix: optional chaining or guard clause
30
+
31
+ ▼ low
32
+ variable name: usr_Obj → user (line 31)
33
+ — convention: camelCase, descriptive noun
34
+ — fix: rename + search-replace in file
35
+ ```
36
+
37
+ Issue comparison:
38
+
39
+ ```
40
+ issue | severity | risk | fix effort
41
+ ──────────────────|──────────|────────────────|────────────
42
+ SQL injection | critical | data breach | 15 min
43
+ null crash | high | prod outage | 5 min
44
+ naming convention | low | readability | 2 min
45
+ ```
46
+
47
+ Fix sequence: null check (5 min, unblock prod) → SQL injection (15 min,
48
+ close security hole) → rename (2 min, cleanup). Total: ~22 min.
49
+
50
+ ## Why this works
51
+
52
+ Issues ordered by severity map to feynman's priority-scale rule (▲▼ markers).
53
+ A multi-criteria comparison of the same issues across dimensions (risk, effort)
54
+ activates the comparison-column rule. Both diagrams together give a complete
55
+ picture — one for prioritization, one for planning.
@@ -0,0 +1,48 @@
1
+ # Database Schema: E-commerce Entity Model
2
+
3
+ ## Question
4
+
5
+ > Show me the relationships between users, orders, and products.
6
+ > Which tables are involved and how do they connect?
7
+
8
+ ## Without feynman
9
+
10
+ Users can place multiple orders. Each order contains one or more line items,
11
+ and each line item references a product. The users table has a primary key
12
+ that the orders table references via user_id. The order_items junction table
13
+ connects orders to products with a quantity field. Products belong to
14
+ categories via a category_id foreign key.
15
+
16
+ ## With feynman
17
+
18
+ ```
19
+ users orders products
20
+ ───────────────────── ───────────────────── ─────────────────────
21
+ id (PK) id (PK) id (PK)
22
+ email (unique) user_id (FK → users) name
23
+ password_hash created_at price
24
+ created_at status stock_count
25
+ total_amount category_id (FK)
26
+ ```
27
+
28
+ Entity relationships:
29
+
30
+ ```
31
+ users
32
+ └── orders (user_id → users.id)
33
+ └── order_items (order_id → orders.id)
34
+ └── products (product_id → products.id)
35
+
36
+ categories
37
+ └── products (category_id → categories.id)
38
+ ```
39
+
40
+ One user → many orders → many order_items → one product per item. Categories
41
+ are a separate hierarchy connected only to products.
42
+
43
+ ## Why this works
44
+
45
+ A database schema is a hierarchy of related entities — feynman's tree-diagram
46
+ and comparison-column rules both activate. Side-by-side columns show each
47
+ table's fields at a glance; the tree shows foreign-key relationships across
48
+ three levels.
@@ -0,0 +1,58 @@
1
+ # Deploy Pipeline: Monorepo CI/CD
2
+
3
+ ## Question
4
+
5
+ > Draw the CI/CD pipeline for our monorepo. We run lint, test, and build in
6
+ > parallel, then deploy to staging, run smoke tests, and promote to production.
7
+
8
+ ## Without feynman
9
+
10
+ The pipeline starts with lint, unit tests, and the build running in parallel.
11
+ Once all three pass the deploy job sends the artifact to staging. After that
12
+ the smoke test suite runs against staging. If smoke tests pass, a manual
13
+ approval gate is required before the production deployment goes out. If smoke
14
+ tests fail, the pipeline stops and alerts on-call.
15
+
16
+ ## With feynman
17
+
18
+ ```
19
+ [push / PR] --> [trigger CI]
20
+ |
21
+ .-----------+-----------.
22
+ | | |
23
+ v v v
24
+ [Lint] [Test] [Build]
25
+ | | |
26
+ '-----------+-----------'
27
+ | all pass
28
+ v
29
+ [Deploy --> Staging]
30
+ |
31
+ v
32
+ [Smoke Tests]
33
+ |
34
+ pass ---+--- fail
35
+ | |
36
+ v v
37
+ [Manual Approval] [Stop + Alert]
38
+ |
39
+ v
40
+ [Deploy --> Production]
41
+ |
42
+ v
43
+ [Rollout health check]
44
+ |
45
+ ok -+- degraded
46
+ | |
47
+ v v
48
+ [Done] [Auto-rollback]
49
+ ```
50
+
51
+ Three parallel jobs gate everything downstream. Production only reachable
52
+ after staging smoke tests and human approval.
53
+
54
+ ## Why this works
55
+
56
+ A pipeline with parallel stages and conditional branches is feynman's
57
+ canonical flow-with-branch pattern. The parallel fork and join shows
58
+ concurrent jobs; sequential arrows show the rest of the path.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@albinocrabs/feynman",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Claude Code and Codex plugin that auto-injects ASCII diagram rules into every AI request via UserPromptSubmit hook",
5
5
  "license": "MIT",
6
6
  "author": "apolenkov",
@@ -38,16 +38,26 @@
38
38
  "skills/",
39
39
  "hooks.json",
40
40
  ".codex-plugin/",
41
+ "docs/",
42
+ "examples/",
41
43
  "install.sh",
42
44
  "uninstall.sh",
43
45
  "README.md",
46
+ "CHANGELOG.md",
47
+ "CONTRIBUTING.md",
48
+ "SECURITY.md",
44
49
  "LICENSE"
45
50
  ],
46
51
  "scripts": {
47
52
  "test": "node --test tests/*.test.js",
48
53
  "coverage": "c8 --reporter=text --reporter=lcov node --test tests/*.test.js",
49
- "ci": "npm run coverage",
50
- "lint": "node bin/feynman-lint.js"
54
+ "lint": "node bin/feynman-lint.js",
55
+ "test:docs": "node scripts/check-docs.js",
56
+ "test:release": "node scripts/release-smoke.js",
57
+ "build": "node scripts/build-package.js",
58
+ "changelog": "node scripts/generate-changelog.js",
59
+ "ci": "npm run coverage && npm run test:docs && npm run test:release && npm run build",
60
+ "prepublishOnly": "npm run ci"
51
61
  },
52
62
  "devDependencies": {
53
63
  "c8": "^10"