docs(steps): the in-order reading, and what validating it found
Spec §3.13.1 describes the rail as built: what it is made of (records the same pass makes as the links), what makes the fold possible (a guard naming the decision it belongs to), the items, and the words. `CLAUDE.md` names `api/program.ts` and what the guard reader now returns. `CHANGELOG.md` gets the user-facing feature and the three fixes under it. Both plans now say what happened: the 2026-08-29 plan carries a BUILT header with where the build differs from it (a guard's `branch`, reading a function once per rail, blocks as one kind carrying facts, loops needing a reading of their own), the answers to its open questions, and a §8 recording the six endpoints read against their source — plus the two gaps left open on purpose, a mongoose `product.save()` the effects table does not know and the nested `const handleX = async () => …` that is still not a node. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01REFyW9hmNrxhwN5wxRoAkC
This commit is contained in:
co-authored by
Claude Opus 5
parent
676030314a
commit
22f92a828b
@@ -571,6 +571,66 @@ one is fitted to the whole stage. `Picture` (`screens-model.ts`) is the structur
|
||||
the shared machinery works over; `steps-model.ts` builds one. Pure model tests: `ui-steps-model.test.ts`; the
|
||||
endpoint against a real RN + Expo fixture: `ui-steps-api.test.ts`.
|
||||
|
||||
#### 3.13.1 In order — the same walk as the code reads (`&view=order`)
|
||||
Rows-by-distance is the right picture for a screen, where handlers fire on events and nothing orders them. It is the
|
||||
wrong one for a handler: on proshop's `POST /api/users/login` the tree puts `User.findOne`, `jwt.sign`, `200` and `401`
|
||||
side by side — each is one step from the anchor — when the code says *look the user up, then IF the password matches
|
||||
sign a token and answer 200, ELSE answer 401*, and the signing happens INSIDE the reply that carries it. So the same
|
||||
walk has a second reading: the anchor, then its body top to bottom.
|
||||
|
||||
```
|
||||
● POST /api/users/login · authUser FIRES FROM POST /api/users/login
|
||||
│ User.findOne({ email }) database · User · read · authUser
|
||||
│ user AND (await user.matchPassword(password))
|
||||
│ ┌ WHEN ───────────────────────┐ ┌ WHEN NOT ──────────┐
|
||||
│ │ via generateToken · inside res.json(…) │
|
||||
│ │ jwt.sign({ id }, …) auth │ │ 401 response │
|
||||
│ │ 200 response │ │ answers here │
|
||||
│ │ answers here │ └────────────────────┘
|
||||
```
|
||||
|
||||
**What it is made of.** Every hop the walk makes is recorded where the code writes it — the step it reached (or the
|
||||
helper it folded into), the call's position and span, the branch guards, the loops, what fires it — by the SAME pass
|
||||
that makes the links, so the two readings can never hold different steps (`WireStepsPayload.program`, built by
|
||||
`src/ui-server/api/program.ts` from the records `steps.ts` keeps; `ProgramSite` is one such record). `buildProgram` is
|
||||
pure over them: no graph, no source, no control-flow graph.
|
||||
|
||||
**What makes the fold possible** is that a guard names the DECISION it belongs to and not only its own words
|
||||
(`BranchGuard.branch` — where the branching construct starts): the `if` and the `else` of one statement carry the same
|
||||
branch with `negated` flipped, an early exit carries the branch of the `if` that returned, every case of a `switch`
|
||||
carries the branch of the switch, and two `try`/`catch` blocks in one function stay apart. Two sites are arms of ONE
|
||||
fork when they agree on the branch and disagree on the arm — which a joined condition string can never say. A guard
|
||||
also carries how the arm it is in leaves (`armExit`) and, for an early exit, how the arm that was not taken leaves
|
||||
(`exit`), so an arm ends with the word the code uses.
|
||||
|
||||
**The items** (`WireItem`): a **step**, where the code writes it — with `inside res.json(…)` when it is written in
|
||||
another call's arguments, its own body under it when the walk entered it, and `again` when the same function has
|
||||
already been read (a function is read once in a rail, however many times it is called); a **fork** — `if` / `switch` /
|
||||
`ternary` / `try` / an early exit — carrying its condition once, with an arm per side, each ending `reply` / `return` /
|
||||
`throw` / `exit` when it stops there; a bracketed **block** — a helper drawn in place (`via generateToken`), a body that
|
||||
runs per item (`for each item of items`, read by `loopsForFile`, which loops and forks nest by which construct BEGINS
|
||||
first), work registered to run later (`later · then`), calls started together (`together · Promise.all`); and a **cut**
|
||||
where the reading stopped. Source order is execution order for straight-line code and for arguments before their call
|
||||
(so the token is signed before the reply); where it is not — a callback, concurrency — the block says so rather than
|
||||
pretending.
|
||||
|
||||
**Honest by construction.** A fork exists only where a guard was READ: a language without rules, or a file that changed
|
||||
since the index sync, reads as a plain sequence rather than an invented structure. Every cap is announced
|
||||
(`program.truncated`).
|
||||
|
||||
**The view.** `ui/src/lib/program-model.ts` decides the words, `StepsRail.svelte` + `RailBlock.svelte` draw them — no
|
||||
layout engine, a column of boxes with a hairline down its left and a fork as a row of arm columns. The box is
|
||||
`StepBox.svelte`, the canvas's box exactly (the canvas wraps it in handles; the rail lets it size to its words), and so
|
||||
are the click, the double-click-to-start-here and the panel. The fork's head says the decision once and its arms say
|
||||
only which side they are — **WHEN** / **WHEN NOT** — except a `switch`, whose arms each have a case to say, and a
|
||||
`try`, which says `on error` once. `StepsKey.svelte` is the key: floating over the canvas, last in the document on the
|
||||
rail, which scrolls and cannot have things sitting on it.
|
||||
|
||||
**Which reading opens** travels in the URL (`&view=order` / `&view=tree`) and the summary offers both; without one the
|
||||
answer's own `defaultView` decides — the code's order for a handler, an endpoint or any function, the tree for a
|
||||
screen. Tests: `ui-steps-program.test.ts` (the fold, over hand-made records), `ui-program-model.test.ts` (the words),
|
||||
and one `in order` reading per framework in `ui-steps-api-servers.test.ts`.
|
||||
|
||||
## 4. Libraries and versions
|
||||
- Svelte 5 (≥ 5.25) + Vite (workspace `ui/`), Svelte Flow `@xyflow/svelte` ^1.6 for the Map and Flow canvases only (custom nodes/edges,
|
||||
hidden handles for port spreading, local selection state — the pattern in docker-app's `StackGraph.svelte`); `@dagrejs/dagre` only as a
|
||||
|
||||
Reference in New Issue
Block a user