Answer the review, and keep the opening node's bank
Nine findings from a review of the phase-14 stack. The one about a retry withdrawing a memory is not a bug — a memory anchored to a node describes that node, and it goes when the node goes. The root is the exception, and it is the only one: migration 62 parked every memory written before memories had coordinates on depth 0, so withdrawing the opening node would retire a whole bank nobody attached there. A memory with no source range covers no story and now stays; a summary that genuinely ends there is still withdrawn. The rest are repairs. * The adventure list quoted whichever attempt was written last rather than the one the story tells, so switching back left the index disagreeing with the page. * A v1 import gave a typed memory no depth, rebuilding the NULL the migration exists to remove — invisible until the imported adventure forked. * The action cap counted a v1 file's turns, and a turn expands into a row per saved attempt, so a file inside the cap could write a multiple of it. * Forking a live node on a borrowed ancestor promoted a sibling on a branch the caller never named. It is a branch switch, and now says so. * Switching attempts left the state, status and memory panels reading the previous take: the story does not change length, so nothing keyed on its length noticed. Same class as the branch-switch bug this phase already fixed. * A retry after switching back numbered the new attempt into the middle of the group instead of the end. * The cursor backfill numbered every action in the table once per adventure; correlated to the adventure being updated, it is an index lookup instead. * Renaming a branch answered own_actions=0. And one behaviour change recorded rather than repaired: script-visible history and actionCount no longer count blank-text rows. That is the right shape and there is no reading compatible with both, so plan/14 says so. 409 tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H5qiyiR7gtFQaoDphHZ3g
This commit is contained in:
committed by
Parth
co-authored by
Claude Opus 5
parent
2d38a162d4
commit
4af6e17406
@@ -321,10 +321,11 @@ def test_forking_a_turn_that_is_already_the_story_is_a_no_op(client):
|
||||
assert len(_branches(client)) == 1
|
||||
|
||||
|
||||
def test_forking_a_single_take_on_another_branch_is_refused(client):
|
||||
"""The only way to reach the refusal, and it names the wrong tool: a node
|
||||
with no siblings is not a divergence, so what the caller wants is to switch
|
||||
to the branch it is on."""
|
||||
def test_forking_a_live_node_on_another_branch_is_refused(client):
|
||||
"""A live node off the path is another line's story, not an attempt going
|
||||
spare — so the refusal names the tool that would actually do it. It used to
|
||||
answer "only one take", which was true of the group and no help at all: the
|
||||
caller does not want another take, it wants the branch this one is on."""
|
||||
discarded = _divergent_story(client)
|
||||
_fork(client, discarded)
|
||||
parent_id = [b for b in _branches(client) if b["parent_branch_id"] is None][0]["id"]
|
||||
@@ -333,7 +334,9 @@ def test_forking_a_single_take_on_another_branch_is_refused(client):
|
||||
|
||||
r = _fork(client, stranded)
|
||||
assert r.status_code == 400
|
||||
assert "one take" in r.json()["detail"]
|
||||
assert "another branch" in r.json()["detail"]
|
||||
# And refusing left the tree alone — the bug this guards is a fork that
|
||||
# promotes a sibling on the branch it was called against.
|
||||
assert len(_branches(client)) == 2
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user