lulz 1.0.3 → 2.0.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.
package/AGENTS.md ADDED
@@ -0,0 +1,609 @@
1
+ # AGENTS.md
2
+
3
+ ## Flow-First Programming: A Manifesto
4
+
5
+ > Software has always been about moving information.
6
+ > We simply forgot to draw the pipes.
7
+
8
+ This document describes **flow-first programming**: a discipline where programs are expressed as readable graphs of **pipes** (facts) and **motions** (transformations).
9
+
10
+ ---
11
+
12
+ ## 0. The Problem We Forgot We Had
13
+
14
+ Most software is a **lie detector's nightmare**.
15
+
16
+ ```js
17
+ // Traditional code: What is happening?
18
+ if (user && user.isValid && !user.banned) {
19
+ const order = processOrder(cart);
20
+ if (order.success) {
21
+ if (payment.charge(order.total)) {
22
+ // 47 more nested conditions...
23
+ }
24
+ }
25
+ }
26
+ ```
27
+
28
+ This code **hides its shape**. You cannot see:
29
+ - What paths exist
30
+ - What outcomes are possible
31
+ - Where errors go to die
32
+
33
+ Flow-first programming has one rule:
34
+
35
+ > **If you can draw it, you can debug it.**
36
+
37
+ ```
38
+ request ──→ validate ──→ price ──→ charge ──→ 'paid'
39
+ │ │
40
+ └──→ 'invalid' └──→ 'declined'
41
+ ```
42
+
43
+ The program **is** the diagram. The diagram **is** the program.
44
+
45
+ ---
46
+
47
+ ## 1. What This Is (and Is Not)
48
+
49
+ This is **not**:
50
+ - an AI abstraction
51
+ - a fancy DSL
52
+ - a new syntax to learn
53
+
54
+ This **is**:
55
+ - a way to see your program's skeleton
56
+ - a shared language for humans and LLMs
57
+ - a method that scales from scripts to systems
58
+ - the spiritual successor to Unix pipes and FFmpeg filtergraphs
59
+
60
+ **The test**: Can a stranger read your program aloud and understand it?
61
+
62
+ ---
63
+
64
+ ## 2. The Two Symbols That Matter
65
+
66
+ Every flow-first program uses exactly two concepts:
67
+
68
+ ### 2.1 Pipes — Named Facts (Nouns)
69
+
70
+ A **pipe** is a named checkpoint. A promise kept.
71
+
72
+ Written as a **quoted string**:
73
+
74
+ ```js
75
+ 'request' // An HTTP request arrived
76
+ 'validated' // Data passed all checks
77
+ 'paid' // Money changed hands
78
+ 'published' // The world can see it
79
+ ```
80
+
81
+ **Pipes are contracts.** When you see one, you can say:
82
+
83
+ > "This happened. I can depend on it."
84
+
85
+ Think of pipes as **milestones on a highway**. They tell you where you are.
86
+
87
+ ### 2.2 Motions — Transformations (Verbs)
88
+
89
+ Anything **unquoted** is motion—work being done:
90
+
91
+ ```js
92
+ validate // check the data
93
+ calculate // compute something
94
+ save // persist to storage
95
+ notify // tell someone
96
+ ```
97
+
98
+ Motions are **honest about uncertainty**. They might:
99
+ - Transform the packet and pass it on
100
+ - Drop the packet silently (this is how branching works!)
101
+ - Create errors
102
+
103
+ **Motions do not promise. Pipes do.**
104
+
105
+ ### The Shape of a Line
106
+
107
+ Every line follows this pattern:
108
+
109
+ ```js
110
+ ['source', motion, motion, motion, 'destination']
111
+ // noun verb verb verb noun
112
+
113
+ // Read it like English:
114
+ // "From source, do this, then this, then this, arriving at destination."
115
+ ```
116
+
117
+ ---
118
+
119
+ ## 3. The Golden Rules
120
+
121
+ ### Rule 1: Producers Begin, Pipes End
122
+
123
+ **Producers** create packets from the outside world:
124
+ - `http` — incoming web requests
125
+ - `stdin` — terminal input
126
+ - `watch` — file changes
127
+ - `socket` — real-time messages
128
+ - `timer` — scheduled events
129
+
130
+ Producers appear **only at the start** of a feature:
131
+
132
+ ```js
133
+ [http, route, 'request'] // ✓ Producer starts the flow
134
+ ['request', process, 'done'] // ✓ Pipe starts subsequent flows
135
+ [process, 'done'] // ✗ Motion cannot start a flow
136
+ ```
137
+
138
+ ### Rule 2: Every Feature Must Name a Pipe
139
+
140
+ A feature isn't done when it runs. It's done when it **commits to a name**.
141
+
142
+ ```js
143
+ // Bad: Where does this go? What can depend on it?
144
+ ['request', handle]
145
+
146
+ // Good: Clear commitment
147
+ ['request', handle, 'response']
148
+ ```
149
+
150
+ ### Rule 3: Motions Drop, Never Branch
151
+
152
+ There is no `if`. There is no `switch`. There is only:
153
+
154
+ > **Forward what you understand. Drop what you don't.**
155
+
156
+ ```js
157
+ ['request', isGetRequest, loadPage, 'page']
158
+ ['request', isPostRequest, saveData, 'saved']
159
+ ```
160
+
161
+ Both lines listen to `'request'`. Each motion decides:
162
+ - "Is this for me? → Forward it."
163
+ - "Not for me? → Drop it silently."
164
+
165
+ **This is how branching works.** The packet finds its own path.
166
+
167
+ ---
168
+
169
+ ## 4. Reading Flows Aloud
170
+
171
+ If you can read it aloud, you can understand it.
172
+
173
+ ```js
174
+ const wiki = flow([
175
+ [http, route, 'request'],
176
+ ['request', loadPage, render, 'viewed'], // loadPage is both a test isLoadPage and page loader, it simply does nothing if not load page.
177
+ ['request', savePage, confirm, 'saved'],
178
+ ]);
179
+ ```
180
+
181
+ Read it:
182
+
183
+ > "HTTP requests become requests.
184
+ > Requests that load pages get rendered and become viewed.
185
+ > Requests that save pages get confirmed and become saved."
186
+
187
+ No translation needed. No mental compiler required.
188
+
189
+ ---
190
+
191
+ ## 5. The Packet's Journey (A Mental Model)
192
+
193
+ Imagine a **letter** traveling through a postal system.
194
+
195
+ ```
196
+ ┌─────────────────────────────────────────────────────────────┐
197
+ │ │
198
+ │ 📧 Packet │
199
+ │ ┌──────────────────────┐ │
200
+ │ │ payload: "Hello" │ │
201
+ │ │ topic: "greeting" │ │
202
+ │ │ _timestamp: 17283... │ │
203
+ │ └──────────────────────┘ │
204
+ │ │
205
+ │ The packet travels through motions: │
206
+ │ │
207
+ │ validate ──→ transform ──→ save │
208
+ │ │ │ │ │
209
+ │ │ │ └─→ Adds { saved: true } │
210
+ │ │ └─→ Uppercases payload │
211
+ │ └─→ Checks format, drops if invalid │
212
+ │ │
213
+ └─────────────────────────────────────────────────────────────┘
214
+ ```
215
+
216
+ Each motion can:
217
+ 1. **Pass it through** unchanged
218
+ 2. **Enrich it** with new data
219
+ 3. **Transform it** entirely
220
+ 4. **Drop it** (the packet simply stops)
221
+
222
+ When the packet reaches a pipe, **that pipe emits**. Listeners wake up.
223
+
224
+ ---
225
+
226
+ ## 6. Patterns That Emerge
227
+
228
+ ### 6.1 The Funnel (Validation)
229
+
230
+ ```js
231
+ ['input',
232
+ notEmpty, // drops empty
233
+ isValidEmail, // drops invalid format
234
+ notDisposable, // drops throwaway domains
235
+ 'validEmail'
236
+ ]
237
+ // Only survivors reach 'validEmail'
238
+ ```
239
+
240
+ ### 6.2 The Fork (Routing)
241
+
242
+ ```js
243
+ ['request', isApi, handleApi, 'apiResponse']
244
+ ['request', isPage, renderPage, 'pageResponse']
245
+ ['request', isAsset, serveFile, 'assetResponse']
246
+ // Each packet takes exactly one path
247
+ ```
248
+
249
+ ### 6.3 The Merge (Convergence)
250
+
251
+ ```js
252
+ ['apiResponse', format, 'response']
253
+ ['pageResponse', format, 'response']
254
+ ['assetResponse', format, 'response']
255
+ // All roads lead to 'response'
256
+ ```
257
+
258
+ ### 6.4 The Fan (Parallel Effects)
259
+
260
+ ```js
261
+ ['order', [
262
+ sendEmail, // notify customer
263
+ updateStock, // adjust inventory
264
+ logAnalytics, // record metrics
265
+ ], 'processed']
266
+ // All three happen simultaneously
267
+ ```
268
+
269
+ ### 6.5 The Saga (Multi-Step Process)
270
+
271
+ ```js
272
+ ['checkout',
273
+ validateCart,
274
+ reserveStock,
275
+ chargePayment,
276
+ confirmOrder,
277
+ 'completed'
278
+ ]
279
+ // Each step must succeed for the next to run
280
+ ```
281
+
282
+ ---
283
+
284
+ ## 7. TODOs Instead of Errors
285
+
286
+ Missing code should not block understanding.
287
+
288
+ The `todo` prefix turns unimplemented features into **work queues**:
289
+
290
+ ```js
291
+ const wiki = flow([
292
+ [todo.http, todo.route, 'request'],
293
+ ['request', todo.loadPage, todo.render, 'viewed'],
294
+ ['request', todo.savePage, todo.confirm, 'saved'],
295
+ ]);
296
+ ```
297
+
298
+ This flow **runs**. It **reads correctly**. It just doesn't do anything yet.
299
+
300
+ You can hand this to an LLM and say: "Implement `todo.loadPage`."
301
+
302
+ The shape is preserved. The poem remains intact.
303
+
304
+ ---
305
+
306
+ ## 8. Examples (Annotated for Beginners)
307
+
308
+ ### 8.1 Static Web Server
309
+
310
+ ```js
311
+ const server = flow([
312
+
313
+ // ─── Entry Point ─────────────────────────────
314
+ [http, route, 'request'],
315
+ // http: produces packets from incoming connections
316
+ // route: parses URL, method, headers
317
+ // 'request': guaranteed to be a valid, parsed request
318
+
319
+ // ─── Static Files ────────────────────────────
320
+ ['request',
321
+ isStaticFile, // drops non-file requests, nothing is sent to readFile
322
+ readFile, // loads from disk (drops if missing)
323
+ detectMime, // adds content-type
324
+ respond, // sends to client
325
+ 'served'
326
+ ],
327
+ // 'served': a file was successfully delivered
328
+
329
+ ]);
330
+ ```
331
+
332
+ ### 8.2 Pastebin
333
+
334
+ ```js
335
+ const pastebin = flow([
336
+
337
+ [http, route, 'request'],
338
+
339
+ // ─── Create Paste ────────────────────────────
340
+ ['request',
341
+ isPost, // drops GET requests
342
+ parseBody, // extracts paste content
343
+ generateId, // creates unique identifier
344
+ store, // saves to database
345
+ 'stored'
346
+ ],
347
+
348
+ // ─── View Paste ──────────────────────────────
349
+ ['request',
350
+ isGet, // drops POST requests
351
+ extractId, // gets paste ID from URL
352
+ retrieve, // loads from database (drops if missing)
353
+ 'found'
354
+ ],
355
+
356
+ // ─── Responses ───────────────────────────────
357
+ ['stored', respondWithLink, 'done'],
358
+ ['found', respondWithContent, 'done'],
359
+
360
+ ]);
361
+ ```
362
+
363
+ ### 8.3 Wiki
364
+
365
+ ```js
366
+ const wiki = flow([
367
+
368
+ [http, route, 'request'],
369
+
370
+ // ─── View Page ───────────────────────────────
371
+ ['request',
372
+ isViewRequest, // drops edits and saves
373
+ loadPage, // fetches from storage
374
+ renderMarkdown, // converts to HTML
375
+ wrapInLayout, // adds header/footer
376
+ 'viewResponse'
377
+ ],
378
+
379
+ // ─── Edit Page ───────────────────────────────
380
+ ['request',
381
+ isEditRequest, // drops views and saves
382
+ loadPage, // fetches current content
383
+ renderEditor, // shows edit form
384
+ 'editResponse'
385
+ ],
386
+
387
+ // ─── Save Page ───────────────────────────────
388
+ ['request',
389
+ isSaveRequest, // drops views and edits
390
+ parseChanges, // extracts new content
391
+ validateContent, // checks for spam, etc.
392
+ saveToHistory, // preserves old version
393
+ saveToStorage, // writes new version
394
+ 'saveResponse'
395
+ ],
396
+
397
+ // ─── Send Response ───────────────────────────
398
+ ['viewResponse', respond, 'done'],
399
+ ['editResponse', respond, 'done'],
400
+ ['saveResponse', respondWithRedirect, 'done'],
401
+
402
+ ]);
403
+ ```
404
+
405
+ ### 8.4 Coding Agent
406
+
407
+ ```js
408
+ const agent = flow([
409
+
410
+ // ─── Intake ──────────────────────────────────
411
+ [stdin, clean, parse, 'order'],
412
+ // User's raw input becomes a structured order
413
+
414
+ // ─── Negotiation ─────────────────────────────
415
+ ['order',
416
+ understand, // LLM comprehends intent
417
+ plan, // LLM creates action plan
418
+ confirm('Proceed?'), // Human approves or rejects
419
+ 'decision'
420
+ ],
421
+
422
+ ['decision', approved, 'greenlight'],
423
+ ['decision', refused, 'rejected'],
424
+
425
+ // ─── Execution ───────────────────────────────
426
+ ['greenlight',
427
+ prepare, // set up environment
428
+ execute, // run the plan
429
+ observe, // check results
430
+ 'result'
431
+ ],
432
+
433
+ // ─── Recovery ────────────────────────────────
434
+ ['rejected',
435
+ explain, // clarify what was misunderstood
436
+ rephrase, // offer alternative
437
+ 'proposal'
438
+ ],
439
+
440
+ // ─── Output ──────────────────────────────────
441
+ ['result', summarize, format, 'output'],
442
+ ['proposal', format, 'output'],
443
+
444
+ ['output', print, 'spoken'],
445
+
446
+ ]);
447
+ ```
448
+
449
+ Delete every function body. **You still understand the system.**
450
+
451
+ That is the point.
452
+
453
+ ---
454
+
455
+ ## 9. Common Mistakes (And How to Fix Them)
456
+
457
+ ### Mistake 1: Returning Instead of Sending
458
+
459
+ ```js
460
+ // Wrong: Functions don't return
461
+ function double(packet) {
462
+ return { ...packet, payload: packet.payload * 2 };
463
+ }
464
+
465
+ // Right: Functions send forward
466
+ function double(options) {
467
+ return (send, packet) => {
468
+ send({ ...packet, payload: packet.payload * 2 });
469
+ };
470
+ }
471
+ ```
472
+
473
+ ### Mistake 2: Explicit Branching
474
+
475
+ ```js
476
+ // Wrong: Traditional if/else thinking
477
+ function router(send, packet) {
478
+ if (packet.method === 'GET') {
479
+ send({ ...packet, route: 'get' });
480
+ } else if (packet.method === 'POST') {
481
+ send({ ...packet, route: 'post' });
482
+ }
483
+ }
484
+
485
+ // Right: Separate motions that drop
486
+ function isGet(options) {
487
+ return (send, packet) => {
488
+ if (packet.method === 'GET') send(packet);
489
+ // Otherwise: silence (packet dropped)
490
+ };
491
+ }
492
+
493
+ function isPost(options) {
494
+ return (send, packet) => {
495
+ if (packet.method === 'POST') send(packet);
496
+ };
497
+ }
498
+
499
+ // Usage: each path is its own line
500
+ ['request', isGet, handleGet, 'response']
501
+ ['request', isPost, handlePost, 'response']
502
+ ```
503
+
504
+ ### Mistake 3: Pipes in the Middle
505
+
506
+ ```js
507
+ // Wrong: Pipe mid-sentence
508
+ ['request', validate, 'validated', transform, 'result']
509
+
510
+ // Right: One pipe per line
511
+ ['request', validate, 'validated']
512
+ ['validated', transform, 'result']
513
+ ```
514
+
515
+ ### Mistake 4: Unnamed Endings
516
+
517
+ ```js
518
+ // Wrong: Where does this go?
519
+ ['request', process, notify]
520
+
521
+ // Right: Commit to a name
522
+ ['request', process, notify, 'notified']
523
+ ```
524
+
525
+ ---
526
+
527
+ ## 10. Why This Works
528
+
529
+ ### For Humans
530
+
531
+ - **Readability**: Programs read like sentences
532
+ - **Debuggability**: Add a `tap` anywhere to see packets
533
+ - **Refactorability**: Move lines around without breaking logic
534
+ - **Onboarding**: New developers understand the system in minutes
535
+
536
+ ### For LLMs
537
+
538
+ - **Structured**: Clear grammar, predictable patterns
539
+ - **Bounded**: Each motion is a small, focused task
540
+ - **Testable**: Easy to verify individual transformations
541
+ - **Extensible**: "Add a motion after X" is unambiguous
542
+
543
+ ### For Systems
544
+
545
+ - **Composable**: Flows embed inside flows
546
+ - **Observable**: Every pipe is an event you can monitor
547
+ - **Resilient**: Dropped packets don't crash the system
548
+ - **Parallelizable**: Independent paths run concurrently
549
+
550
+ ---
551
+
552
+ ## 11. The Philosophy
553
+
554
+ Flow-first programming rests on three beliefs:
555
+
556
+ ### Belief 1: Shape Over Syntax
557
+
558
+ The **topology** of a program matters more than its tokens.
559
+ If you can see the shape, you can reason about behavior.
560
+
561
+ ### Belief 2: Silence Over Exceptions
562
+
563
+ When a motion doesn't apply, it drops the packet.
564
+ No errors. No catches. No noise.
565
+ The packet simply takes another path—or no path.
566
+
567
+ ### Belief 3: Names Over Comments
568
+
569
+ A well-named pipe is worth a thousand comments.
570
+ When `'validated'` appears, no explanation is needed.
571
+ The name carries the meaning.
572
+
573
+ ---
574
+
575
+ ## 12. Getting Started
576
+
577
+ 1. **Draw first**. Sketch the flow on paper before coding.
578
+ 2. **Name your pipes**. What are the important states?
579
+ 3. **List your motions**. What transformations connect them?
580
+ 4. **Wire it up**. Write the flow array.
581
+ 5. **Implement motions**. One small function at a time.
582
+
583
+ Start with `todo.` prefixes. Let the shape emerge.
584
+ Fill in the implementations later.
585
+
586
+ The program will tell you what it needs.
587
+
588
+ ---
589
+
590
+ ## 13. A Final Word
591
+
592
+ > Programs should be written for people to read,
593
+ > and only incidentally for machines to execute.
594
+ > — Abelson & Sussman
595
+
596
+ Flow-first programming takes this seriously.
597
+
598
+ The graph is the spec.
599
+ The graph is the documentation.
600
+ The graph is the test plan.
601
+ The graph is the program.
602
+
603
+ Draw your pipes.
604
+ Name your truths.
605
+ Let the packets flow.
606
+
607
+ ---
608
+
609
+ *End of AGENTS.md*