Put the pager back, and let any turn be played again
SP7 replaced the pager with chips, on the grounds that a chip could also offer "take this path" while a pager could only step. Driving it by hand said otherwise, and the reason is worth keeping: the chip meant two different things depending on where the reader was standing -- a real switch at the tip, a preview needing a second button above it further back. Two meanings in one control is what made the tree unusable. So: one control that does one thing. Stepping reads a take and nothing else, and it tells the server nothing, because reading is not a decision. The transcript below a take that is not live simply ends -- such a take is a leaf by construction, since whatever was played after the turn was played after the take that *is* live. The decision is made by writing, and `after_id` carries it. One step does reach the server and is still not a fork: a take with a story of its own lives on its own branch, so going there is a branch switch and only the server can say what is underneath. `branch_id` on the take is what tells the two apart without asking first. And a fork button on every turn but the opening. On the AI's it regenerates; on your own it opens the text so you can say something else. What the story made of the old take is kept, on the line it was written on. `selectVariant` and `forkFromAttempt` leave the client. Both endpoints stay -- tested, and `stand_on` is shared with the write path -- but the pager needs neither. 426 backend tests; lint and build clean. Not yet driven by hand: the frontend still has no test runner, so this needs the `--keep` fixture and eyes, exactly as SP7 did. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Dvvqn9ZDR4ixeFPHNbww7
This commit is contained in:
committed by
Parth
co-authored by
Claude Opus 5
parent
ea7336e5d3
commit
f9b836fc0b
+20
-8
@@ -105,10 +105,15 @@ export const api = {
|
||||
// attempts themselves are fetched when the reader actually pages through.
|
||||
listVariants: (advId, actionId) =>
|
||||
request(`/adventures/${advId}/actions/${actionId}/variants`),
|
||||
selectVariant: (advId, actionId, index) =>
|
||||
request(`/adventures/${advId}/actions/${actionId}/variant`, {
|
||||
method: 'POST', body: JSON.stringify({ index }),
|
||||
}),
|
||||
// The same endpoint under the name the pager uses. "Take" is what the UI
|
||||
// calls one of these now, and the vocabulary is worth keeping straight —
|
||||
// `variant` belongs to the pre-tree pair of columns SP8 drops.
|
||||
listTakes: (advId, actionId) =>
|
||||
request(`/adventures/${advId}/actions/${actionId}/variants`),
|
||||
// No `selectVariant` / `forkFromAttempt` here any more. Both endpoints still
|
||||
// exist and are tested, but the pager needs neither: stepping between takes
|
||||
// tells the server nothing, and what used to be "take this path" is now
|
||||
// whatever the reader writes next, carried by `after_id` on the turn itself.
|
||||
|
||||
// The story tree (Phase 14). One request draws the whole shape however many
|
||||
// forks there are. The three that change it answer with the story as it now
|
||||
@@ -122,11 +127,18 @@ export const api = {
|
||||
}),
|
||||
deleteBranch: (advId, branchId) =>
|
||||
request(`/adventures/${advId}/branches/${branchId}`, { method: 'DELETE' }),
|
||||
// Take the story down one attempt. A fork only when it has to be: while the
|
||||
// attempts are still at the tip they are leaves, and the server switches.
|
||||
forkFromAttempt: (advId, actionId) =>
|
||||
request(`/adventures/${advId}/actions/${actionId}/fork`, { method: 'POST' }),
|
||||
// Play a turn again, differently (SP9). An AI turn regenerates; a player's
|
||||
// own takes the text given. Streams, because it is a turn like any other.
|
||||
//
|
||||
// Reaches any turn, not only the newest — which is the whole difference from
|
||||
// `retry`, and the reason the pager can offer this on every message.
|
||||
addTake: (advId, actionId, text, handlers, signal) =>
|
||||
streamSSE(`/adventures/${advId}/actions/${actionId}/takes`, { text }, handlers, signal),
|
||||
|
||||
// `afterId` names the take the turn is played after. Omitted it means the
|
||||
// tip, which is every ordinary turn. Naming a take the story moved past is
|
||||
// what forks a branch — stepping between takes to read them does not, and
|
||||
// the server is never told about it.
|
||||
sendAction: (advId, payload, handlers, signal) =>
|
||||
streamSSE(`/adventures/${advId}/actions`, payload, handlers, signal),
|
||||
retry: (advId, handlers, signal) => streamSSE(`/adventures/${advId}/retry`, {}, handlers, signal),
|
||||
|
||||
Reference in New Issue
Block a user