|
| 1 | +--- |
| 2 | +name: ideal-pseudocode |
| 3 | +description: Function-by-function refactoring loop driven by ideal pseudocode. Use when the user says "ideal pseudocode", asks to make a function read like its pseudocode, or wants a dense module cleaned up one function at a time. |
| 4 | +--- |
| 5 | + |
| 6 | +# Ideal Pseudocode |
| 7 | + |
| 8 | +Clean up one function at a time by writing the pseudocode it _should_ read as, naming every delta between that and the real code, and closing only the gaps the user approves. |
| 9 | + |
| 10 | +## Loop |
| 11 | + |
| 12 | +One function per round. Never touch code before the user picks a direction. |
| 13 | + |
| 14 | +1. **Pick the target** with the user — usually the next function up or down the call chain from the last round. |
| 15 | +2. **Read the current code** fresh from disk. It may have unsaved or parallel edits; ask before overwriting anything unexpected. |
| 16 | +3. **Distill.** Write the function's ideal pseudocode in a `ts`-fenced code block — TypeScript-flavored for syntax highlighting, but pseudocode: comments over mechanics, one line per idea, every arm of a loop visible as an arm. For a dense or unfamiliar function, first show the _current_ structure as pseudocode, then the ideal. |
| 17 | +4. **Name the deltas.** A numbered list; each delta is one concrete gap: control flow smuggled through combinators, a flag-typed parameter, colliding names, side-effect plumbing drowning a loop body, twin functions differing only by a filter. For each, give an honest cost/benefit and a decisive recommendation — including "leave it" when the density has reasons (state the reasons). |
| 18 | +5. **Verify before proposing.** Any API the proposal builds on (a combinator, schedule, matcher) gets checked against the installed version's source, not memory. |
| 19 | +6. **Get buy-in, then apply.** Minimal edits. Quarantine irreducible ugliness inside a small helper whose name is the pseudocode line it implements. Collapse shallow sibling functions into one deep function only when the distinguishing argument is a domain noun, not a behavior switch. |
| 20 | +7. **Validate.** Typecheck and the focused test suites from the package directory; rerun timing-sensitive tests repeatedly. Flag any semantic change the restructure introduced, even when tests pass. |
| 21 | +8. **Offer the next target** and stop. |
| 22 | + |
| 23 | +## Style |
| 24 | + |
| 25 | +- Keep each round tight: pseudocode block, deltas, recommendation, one question. |
| 26 | +- State mutation belongs in one visible place (usually the loop tail), never spread across error channels or callback closures. |
| 27 | +- Prefer early return and `if` chains for control flow; matchers are for producing values. |
| 28 | +- Compare names against the question each caller is actually asking; rename toward the domain noun. |
| 29 | + |
| 30 | +## Example round |
| 31 | + |
| 32 | +Every round should read like this (abridged from a real one, on an Effect step-runner): |
| 33 | + |
| 34 | +> `runStep` it is. The ideal pseudocode: |
| 35 | +> |
| 36 | +> ```ts |
| 37 | +> // One logical step: one settled model call, however many attempts it takes. |
| 38 | +> // An attempt can end without settling in two ways: |
| 39 | +> // transient provider failure -> retry the same call, same assistant message |
| 40 | +> // compaction rewrote history -> rebuild the request and call again |
| 41 | +> function runStep(session, promotable, step) { |
| 42 | +> while (true) { |
| 43 | +> const result = callModel(session, promotable, step) |
| 44 | +> |
| 45 | +> if (result.completed) return result |
| 46 | +> |
| 47 | +> if (result.retryable) { |
| 48 | +> wait(retrySchedule) // exhausted -> publish Step.Failed, fail drain |
| 49 | +> promotable = none // never re-promote on a second attempt |
| 50 | +> continue |
| 51 | +> } |
| 52 | +> |
| 53 | +> // compaction restarted the step: fresh request from rewritten history |
| 54 | +> promotable = none |
| 55 | +> step = result.step |
| 56 | +> } |
| 57 | +> } |
| 58 | +> ``` |
| 59 | +> |
| 60 | +> Comparing against the real thing, three deltas: |
| 61 | +> |
| 62 | +> 1. **The retry arm doesn't live in the loop.** In the pseudocode, retry is just another loop arm. In the real code it's smuggled through the error channel: `Effect.tapError` mutating loop variables via `Effect.sync` closures, then `Effect.retryOrElse` re-running a suspended call. Four mutable variables mutated from three different places — the state flow is invisible unless you already know the trick. |
| 63 | +> 2. **`recoverOverflow: typeof compaction.compact | undefined`** — a function-typed parameter used as a one-shot armed/disarmed flag. The callee already closes over `compaction`; a boolean says what it is. |
| 64 | +> 3. **`assistantMessageID`** exists solely to resume the same durable message across retries — fine, but only legible once the retry arm is visible in the loop. |
| 65 | +> |
| 66 | +> The unifying move for (1): a schedule driver, so a retryable failure becomes a caught value handled in the loop body exactly like the compaction arm. One honest trade: it's more manual than the blessed combinator — but the manual version is the loop the combinator was hiding, and the loop already exists for restarts. Two restart mechanisms, one control structure. |
| 67 | +> |
| 68 | +> Want me to apply it — unified loop, simplified schedule input, boolean `recoverOverflow`? |
0 commit comments