Repository navigation
Cycle 0052: replays leave, move and open without stale frames, and every Cycle 0051 carried defect is closed #124
Description
Outcome
Every defect that Cycle 0051 carried is closed, by a fix with a test that fails without it or by recorded evidence. This is a bug-fix cycle: it follows #122, which closed with 24 carried defects (its closing comment). It adds no increment: nothing is selected, dropped or reduced (AGENTS.md, Cycle rule).
- Learner. Test and browser replays leave, move and open without stale frames: no leftover CodeLens, no Study page in the Learning summary, no transport from the wrong replay family. Entries and exits behave as the learner chose.
- Agent. A live test run survives a required fact it cannot read. A browser run's refusals say where a stop can go.
- Engineering. The tests stop pinning implementation constants and fixed waits. The doc comments sit on the right functions.
Verified current state. Base: main at bd082540, v0.2.39.0, read on 2026-10-24. Each task cites the code that produces its defect at that revision.
Abbreviations:
- W =
extension/src/studyWorkspace.ts - H =
extension/src/ui/studyHtml.ts - TC =
extension/src/tests/studyWorkspaceTestReplayComposition.test.ts - TO =
extension/src/tests/studyWorkspaceTestReplayOpens.test.ts - TB =
extension/src/tests/studyWorkspaceTestReplayBrowser.test.ts - TS =
extension/src/tests/studyWorkspaceTestReplaySource.test.ts - QA =
extension/scripts/study-bootstrap-qa.mjs
Done when:
- All 24 tasks below are checked, each with "fixed in " or "evidence: ".
- The N52 native round passes in both hosts, as described below.
- The 15-check exact-tree gate passes on the final tree, and required CI passes on the exact head.
Tasks
The source of every task is Cycle 0051 (#122), with the label named. A finding made during this cycle becomes one more task. Proof is one of these three:
- A product fix (tasks 1–7, 11–21, and 24 when it finds a group) lands with a test that is red on
bd082540and green after the fix. - A test-quality task (tasks 8, 10, 22) proves its tests by a temporary mutation of the behavior they protect: each test is red under the mutation, and the PR records it.
- A defect found during this cycle lands with a test that is red on the commit before its fix.
When a red test needs harness code added later in this cycle, only that test support is ported to the base for the red run. A compile failure or a missing fixture is not a red result.
Evidence closes only the tasks whose Closes line allows it (6, 7, 9, 23, 24). Evidence names the observation and where it is recorded.
-
N51-V1: a stale CodeLens during a pending move. Fixed in
75dec02f(no CodeLens, O8) andf0c11ead(the placeholder goes in at line 1); host tests red without each fix; N52 (b) PASS in both hosts onf0c11ead(Cursor take 2380d57ee…, VS Code take 1e2166ac6…).- Defect:
leaveNodeHistoryMoment(W:25003-25006) clears the slot'sstopand firesslotLensChanges. The editor still draws the previous stop's label (Recorded: app/lib/actions.ts:35 · 20.56 s) beside the pending target until it asks the provider again: 2 to 3 frames in VS Code, about 9 in Cursor (W:779 notes the 300 ms settle,NODE_HISTORY_LEAVE_SETTLE_MS). In Cursor, a move to an output also keeps the old source's sticky-scroll header for 2 frames. - Closes: no frame of a pending move shows the previous stop's label or header. The fix withdraws the label in the same step as the decoration, for example a pending lens whose title names the target, or no lens.
- Defect:
-
N51-V2: the summary is not withdrawn when a test replay retires. Fixed in c4a7f6e (test red on
bd082540, green after).- Defect:
retireNodeHistorySelection(W:12743-12773) never callsclearLearningSummary.leavePlayback(W:12712-12723) returns early for a test replay becauserecordingActiveis false. The summary is cleared only by the lateropen()(W:8192-8193). Any publish before that open draws the Live Study content in the Learning summary: 1 to 3 frames in N51. - Closes: a test replay's retirement withdraws the summary before any publish, as a browser replay's departure does.
- Defect:
-
N51-V3: a test-family transport shows during a departure. Fixed in c4a7f6e (test red on
bd082540, green after).- Defect:
shownReplayFamily()(W:13588-13591) returnstestfor any summary composition without a recording.leavePlaybacksetsrecordingActive=falsewhilesummaryCompositionstays true untilopen()recomputes it, so publishes in that gap (W:12772, W:12815,refresh/renderSelectionbefore W:9170, and Reload at W:8900) sendreplayFamily:'test'with no history. N51 saw 1 to 2 frames ofTest journal playbackin the bottom panel on Return to Live from both families. - Closes: the family comes from what is shown (a selected or opening test replay), never from the absence of a recording.
- Defect:
-
N51-V4: the Application tab keeps a browser title. Fixed in c4a7f6e (test red on
bd082540, green after).- Defect:
ensureReplayViewport(W:12417) setscodebook · Recorded application. Nothing renames the panel on departure:dropReplayViewportcloses the viewport without disposing the panel, andpresentNodeHistoryApplication(W:15063-15091) writes only HTML. So the title stays in the Live composition and in a later test replay. - Closes: after leaving a browser replay, the Application pane's title is
codebook · Application(its creation title, W:18863) in the Live composition and in a test replay. During a live run it stays the live lease's title,codebook · Application <run id, 8 characters>.
- Defect:
-
N51-V5: a live run ends on an unreadable required fact. Fixed in
cadafe96. The root cause is recorded in this Issue: imported names live only in Vitest's module bindings. Tests red on83f9128e: four inspector cases, the owned-run stop and the service refusal (EVIDENCE_UNAVAILABLE, run paused, next continue goes on). N52's live observation follows on pt3's candidate.- Defect:
inspectNodeTestVariables(utils/inspectNodeTestVariables.ts:62-70, called fromownedNodeTestRun.ts:691) throwsRequired Node debugger fact is unavailable or too large: value:revalidatePath.mock.calls.length.continueNodeTest(service.ts:1561, :1593-1595) turns it intoRUNTIME_FAILED, which ends the run. - Closes:
- The root cause of this path is recorded in this Issue: whether the inspector cannot walk
mock→calls→length(properties of a function and an array in the debugger's variables), or whether the value exceedsREPOSITORY_LITERAL_LIMIT_CHARS(1,024). - A path the debugger can read is read.
- A required fact that still cannot be read refuses that
codebook_continuecall with the existingEVIDENCE_UNAVAILABLEcode, and the text names the fact. The run stays paused at the same stop, so the agent can continue without that fact. MCP 1.8's schema is unchanged; only the code and the run's state after the refusal change. Optional facts keep today's omission.
- The root cause of this path is recorded in this Issue: whether the inspector cannot walk
- Defect:
-
N51-V6: a browser replay's open shows the Study document first. Fixed in c4a7f6e (test red on
bd082540, green after).- Defect: the summary view gets the generic
studyHtml('context')document, then a publish insideopen()(W:19775-19778, W:19318-19323, W:8542-8549).loadPlaybackcalls that open (W:12258) before the presented bundle exists, so 1 frame of Study content shows before the replay's summary. Return to Live shows the same frame. - Closes: the summary view receives no Study message before its replay's first message, on a browser replay's open and on its Return to Live. This holds whether or not
mainbefore Cycle 0051 (8dd675b9) shows the frame. Close by evidence only if the host test shows no such message and N52 shows no such frame.
- Defect: the summary view gets the generic
-
N51-C2: a browser run of a page link found no stop and sealed partial. Both parts closed in
761500dd, with root causes recorded in this Issue.-
7a: the interrupted seal. Fixed: the seal names the run's own failure (test red on
cadafe96). -
7b: the stop outside the launched route's chunks. Evidence of the boundary (a stop is armed before input in the launched route's client code), and the refusal now names the file and the page and says where a stop can go (test red on
cadafe96). -
Defect: a Cursor Agent run of the top page's Log in link to
/loginwas refused. The refusal:Selected source is absent from the selected application route chunks; verify that it belongs to the launched page(utils/readDevelopmentBundle.ts:117-134;configuredBrowserRun.ts:584). It retried with other stops. Its recording sealed withRuntime interrupted or cleanup incomplete; recorded prefix retained.(service.ts:3620-3627), with no application frame and no source. -
Closes: a root cause, recorded in this Issue, for each of two questions:
- (a) Why the seal reports an interrupted run when the AI stopped the run itself.
- (b) Whether a stop in the navigation target's client component (
app/ui/login-form.tsx) can be armed once its chunk loads.
Each part closes by a fix with its test, or by evidence of a documented boundary (the run profile cannot arm a stop outside the launched route's client chunks). If evidence, the refusal sentence is changed to name where a stop can go (the launched route's client chunks), so the agent does not retry blind. That change is a fix with its test.
-
-
Fixed waits in three host tests (/ship review). Fixed in
30cb0bbe: the timer tests wait for the retired controller to clear its timer and hold no event, and the superseded-move test awaits that move's handling. Mutation proof: astopTimerthat clears nothing, or a retirement that neither pauses nor disposes, turns both timer tests red; a superseded move that reports a refusal turns the third red.- Defect: TC:769-770 and TC:799-800 wait
setTimeout(resolve, 600), and TC:943-944 waits 100 ms, each markedgstack-timing-ok. - Closes: each wait becomes an await on the observable it stands for (the harness's event or state), keeping real production deadlines (AGENTS.md, Commands and checks).
- Defect: TC:769-770 and TC:799-800 wait
-
Doc comments above the wrong functions (/ship review; CodeRabbit). Evidence: comment-only diff
cad14578, lint and typecheck pass.- Defect:
- H:787-791 (
playTestReplayControl's JSDoc) sits aboveplayTransportControl's JSDoc; the function at H:814 has none. - H:2469-2474 (
testReplayTitle) sits aboverenderFamilyTransport's JSDoc; the function at H:2517 has none. - H:2077-2081 (
focusSummaryStart) attaches tocontrolEverFocused(H:2083), not to the function at H:2088. utils/describeNodeTestReplay.ts:38(Show more and less) sits above theplayingStatusdoc.
- H:787-791 (
- Closes: each block stands directly above its own symbol.
- Defect:
-
Test expectations pinned to implementation constants (CodeRabbit). Fixed in
2e8b9b9a: both expectations are literals; changing either constant's text turns its tests red.- Defect: TC:195 compares a notice with
SUMMARY_PLACEMENT_OFFER, and TC:838 withSTUDY_REMOVAL_REFUSALS.nodeHistory; the constants are imported at TC:8-9. - Closes: both expectations are hard-coded literals (AGENTS.md, DAMP).
- Defect: TC:195 compares a notice with
-
An unanswered notice holds the entry turn (/ship review). Fixed in
75dec02f(host test red ond4ecc320).- Defect:
enterCompositionForEntryawaits the non-modal "Close browser replay" notice inside the turn (W:11697-11707, W:11770-11775). Every later Open replay or Saved studies entry waits onpreviousTurnuntil the learner answers. - Closes: a later entry is not blocked by an unanswered notice. It supersedes it, or it proceeds, and an answer to the old notice closes nothing (README's existing sentence).
- Defect:
-
Close and Return to Live do not invalidate a waiting entry (/ship review; Codex P2). Fixed in db06b20 (test red on
bd082540, green after).- Defect: neither
close()(W:9446-9480) norreturnCurrentSelection(W:9131-9186) bumpsnodeHistoryEntryRequest, and the entry flow takes no lifetime (W:11695-11712, W:11833-11835). After Close, a waiting second Open replay passes its ticket checks, andopen()reopens the reader the learner closed. - Closes: Close and Return to Live retire every waiting entry, and a retired entry changes no view, focus or selection.
- Defect: neither
-
A stale-revision Saved studies open leaves an empty summary composition (/ship review). Fixed in db06b20 (test red on
bd082540, green after).- Defect: the summary composition is entered first (W:11704). A stale
message.revision(W:23097) makeshistoryOpenSupersededreturnsuperseded.openNodeHistorytreats that as success (W:12120-12122), soleaveEmptySummaryComposition(only at W:11745 and W:11806) never runs. - Closes: a superseded open with no newer replay leaves the summary composition, as a failed open does: the Study pane comes back on Saved studies.
- Defect: the summary composition is entered first (W:11704). A stale
-
Open replay with the summary and the bottom panel both hidden shows nothing (/ship review). Fixed in b37912f (test red on
bd082540, green after).- Defect:
enterSummaryCompositionForReplay(W:11826-11832) returns early when the reader is already in the summary composition, soshowLearningSummaryand the Observed moments reveal never run. The hidden views stay hidden. - Closes: Open replay always ends with the summary shown and focusable. The learner's other layout choices (panel sizes, unrelated groups) are kept.
- Defect:
-
A browser study chosen from a test replay's summary bypasses the editor-area deferral (/ship review). Fixed in b37912f (test red on
bd082540, green after).- Defect:
showSavedStudydefers withstudyAwaitingEditorAreawhile the editor area is hidden (W:24514-24521).showChosenStudythen callsleaveEmptySummaryComposition, thenopen()andrenderSelection, which clears the deferral (W:13734) and shows the panes anyway (W:23302-23303, W:11847-11857). - Closes: the deferral holds until the editor area is shown, as from the Study pane.
- Defect:
-
showLearningSummaryfails an open when its identity changes (/ship review, Red Team). Fixed in b37912f (test red onbd082540, green after).- Defect:
assertCurrent(W:19262, W:19276-19279) throwsSTALE_PRESENTATIONwhenshownReplayIdentity()changes during the awaits of the move, focus andwaitUntil. The throw leavesopen()(W:8544) and fails that entry. - Closes: a summary reveal superseded by a newer selection ends quietly. The newer selection's reveal wins, and no entry reports a failure for it.
- Defect:
-
Every move failure is worded as a debugger failure (/ship review). Fixed in
75dec02f(ReplayDebuggerStartError; host and unit tests red ond4ecc320; slot, Application pane and layout failures do not reach this sentence, they keep their own rows).- Defect:
describeNodeHistoryMoveFailure(W:24930-24935, thrown at W:24759) saysThe replay debugger could not start: …for every error frompresentNodeHistoryDebuggerOrKeepOpen, whatever its cause. - Closes: the sentence follows the cause:
- A failure of the replay debugger's start keeps today's sentence and recovery clause.
- Any other failure reads
The recorded moment could not be shown: <cause>. The last moment is still shown. Select this stop again to retry.That covers the recorded-source slot, the Application pane and the layout. <cause>is sanitized as today.
- Defect:
-
forgetUnopenedCompositionand a Reload race can leave or blank the summary (/ship review). Fixed in b37912f (test red onbd082540, green after).- Defect:
forgetUnopenedComposition(W:8634-8640, called at W:8585-8586) dropssummaryCompositionbut leaves the summary document. Reload (W:8895-8902) runsleavePlayback(true), thenopenRecording.recordingActiveis false untilloadPlaybacksets it again (W:12190), so anotheropen()in that gap clears the summary the Reload kept. - Closes: a failed first entry withdraws its summary document. A Reload keeps its summary until its own load ends, unless a newer selection supersedes the Reload: another replay, Return to Live or Close. Then the summary follows that selection. An
open()that changes no selection (Restore, Arrange, focus) never blanks it.
- Defect:
-
Step marks are bound by SVG sibling order (/ship review). Fixed in
75dec02f(Reader DOM case red ond4ecc320inredmode).- Defect:
tagTestReplayDrawing(H:3019-3031; drawing at H:2407-2434) pairs steps with arrows by their order and labels bynextElementSibling, never by an id from the renderer. - Closes: the renderer writes each arrow's and label's step id. The marker reads that id. A drawing whose arrows are reordered or interleaved still marks the right step.
- Defect:
-
Show more's expanded state persists across replays (/ship review). Fixed in
75dec02f(Reader DOM case red ond4ecc320inredmode).- Defect: the only state is the button's
aria-expanded(H:224; toggle H:3097-3108; read H:3085; called H:4258), and nothing resets it when the replay changes. - Closes: every open of a test replay starts with every clamped text collapsed, whether the replay is another one or the same one opened again. Moves inside the open replay keep the learner's expanded texts.
- Defect: the only state is the button's
-
nodeHistoryRefusalis not sanitized at publish (/ship review). Fixed in75dec02f(host test red ond4ecc320).- Defect: W:13377-13380 publishes
String(error)minusError:(stored byreport, W:25934-25938), without the path cleaningreportTestReplayFailure(W:12037-12047) anddescribeNodeHistoryMoveFailure(W:24931) apply withsanitizeCause. - Closes: the published refusal has the storage folder replaced, as the other replay failures do.
- Defect: W:13377-13380 publishes
-
Untested state cells (/ship coverage audit). Add the tests; any defect they find becomes a task. Fixed in
26c4878c: two host cases (TB) and two Reader DOM cases. The failed-open cell found task 59. Red proof: a page mutation for each Reader DOM case fails exactly that case underred.-
Gap:
- a browser replay × another saved study;
- a browser replay × a failed open;
- the browser replay's Replay from start and Pause clicks (
playBrowserReplayControl, H:806-813).
-
Today's coverage: QA:1137-1160 clicks only Previous and Next on a browser replay, and the Replay from start cases (QA:10603-10620) are test-family only.
-
Closes: each cell has a passing test asserting today's contract:
- Another saved study chosen during a browser replay: the browser replay retires (playback left, summary withdrawn) and the chosen study shows in its own composition.
- A failed open of a browser replay: the load-failure notification, one Output › Codebook entry, the previous reader state kept, and no summary composition left empty.
- Replay from start: sends a seek to the recording's start, and the readout shows its start time.
- Pause: sends
pause, and the toggle reads Play.
The carried patch from Cycle 0051's /ship (a private artifact) holds drafts.
-
-
Two stale comments (/ship review). Evidence: comment-only diff
cad14578.- Defect:
- W:11494 says
A test replay opens in the Study pane, not through the browser replay's controller.It now opens in the summary composition. studyWorkspaceTestReplayPane.test.ts:114says the Study pane's group stays the right column, which the summary composition no longer has.
- W:11494 says
- Closes: both comments state current behavior.
- Defect:
-
An empty editor group in the composition (/ship review). Evidence: with VS Code's default
closeEmptyGroupsmodeled, the host case leaves no empty group (test in f028933). The empty group the first run showed came from the harness keeping a group emptied by a move; N51 saw none natively in either host. N52 observes it again.- Defect: the harness starts with two groups and never removes an emptied one (
studyWorkspaceHarness.ts:446-454, :1073-1074, :1138, :1145-1146). So when the Study pane closes in the summary composition (contextPanel.dispose(), W:8201), an empty group would go unnoticed. N51 saw none in either host. - Closes: a host case with
closeDisposedPanelTabsLater(harness :5885) shows whether the composition leaves an empty group. If it does, fix it with that test. If not, close with the test and N52's observation as evidence.
- Defect: the harness starts with two groups and never removes an emptied one (
-
Found in this cycle: the Study's article source tab stands beside the recorded-source tab. Evidence (no defect): README's sentence promises that a test replay's open does not open the article source. An article tab that was already open from the Study composition stays: the summary composition's layout receipts and Restore use it as the source anchor (
studyWorkspace.ts, F402). A trial fix that closed it broke 11 Restore and layout-confirmation host tests, so the layout depends on that anchor.- Defect: a test replay opened from the Study composition keeps the Study's
Captured-overview.mtstab, which moves into the recorded-source tab's group. Seen in the harness and in N51's Cursor frames (actions.ts,Captured-overview.mts,Captured-actions.ts). README promises noCaptured-overviewtab beside the replay's recorded-source tab. - Closes: the replay's open closes the reader's own unpinned, unedited article source tab once, as it does for a retired browser replay's captured source.
- Proof: a host test that is red before the fix.
- Defect: a test replay opened from the Study composition keeps the Study's
-
Found in this cycle: a Retry storage test failed once under the full parallel run. Fixed in
10dd6d83(test timing): the second run's refused save goes through the write queue afterrefresh()returns, and under load the refusal came after the Retry ended. This test and its sibling now wait for that refusal first. A 400 ms delayed refusal fails both on26c4878c(3/3) and neither after; the line-retirement mutation fails both 5/5, before and after.- Defect:
studyWorkspaceRemoval.test.ts, "a Retry storage / refresh that saved the earlier study keeps the line …", failed once in the full run of the workspace partitions. It passed 3 of 3 alone. - Closes: a root cause (a timing dependency in the test or in the code) fixed with its test, or evidence from repeated full runs.
- Defect:
-
Found in this cycle: a Wiki publisher test failed once inside
pnpm health's coverage run. Fixed in550b5ec0(product). Root cause: Update anyway's start claimed the marker while this window's ended run still turned it into a reservation under the claim, so it refused itself withAnother editor window is starting or ending an update of this Wiki. The start now waits for its own window's change and claims again. 24 parallel runs: 9 and 7 failures in 96 before, 0 in 96 after; a host test holding the reservation's write is red without the fix.- Defect: in
wikiUpdatePublisherFlow.test.ts, "after a VS Code watch ended on a learner's file, Update anyway on the one refusal of the next press starts the update again …" got['Open LLM Wiki']where['Update anyway', 'Open LLM Wiki']was expected. It happened in the pt1 gate onaddf2e20, so health refused to measure. The file passed alone. The test belongs to an area this cycle did not change. - Closes: a root cause (a timing dependency in the test or the code) fixed with its test, or evidence from repeated health runs.
- Defect: in
-
Found in this cycle (pt1 /ship review, state-machines specialist): a saved study chosen during or after a failed same-study Reload keeps the old replay's composition. Fixed in
40d30aa1.- Defect: the Reload mark (
recordingReloadStudyId, task 18) holds the summary composition, butopenChosenStudyrouted the choice byrecordingActivealone, andselect()rendered a Study item, so the reader stayed in the browser replay's summary composition for a recording that was gone, or drew a Study item under it. - Closes: while the mark is set the reader counts as showing its browser replay (
browserReplayShown()): a saved-study choice opens the chosen recording as during the replay, and a step selection is refused until the recording has loaded again. - Proof: host tests red on
35e0215e.
- Defect: the Reload mark (
-
Found in this cycle (pt1 /ship review, Red Team): an agent reads a reader in a same-study Reload as following the run. Fixed in
40d30aa1.- Defect:
presentationState()reportedcontentTabandfollowingCurrentRunfromrecordingActivealone, so during a Reload (loading or failed) an agent could start a new run without returning to it, while the reader showed the browser replay; the failed load's reason was not reported. - Closes: while the mark is set,
contentTabreadsrecording,followingCurrentRunis false and the failed load's reason is reported; the agent's Return runs. - Proof: host test red on
35e0215e.
- Defect:
-
Found in this cycle (pt1 /ship review, state-machine cell entry-opening × Return): a Return to Live while a test replay is opening leaves the reader loading. Fixed in
40d30aa1.- Defect: the Return bumps
historyRequest, but the open's marker (pendingNodeHistory) kepttestReplayHoldsComposition()true through the Return, so the Return could not arrange Live; when the held open resumed it ended superseded and, no longer the latest request, leftloadingtrue. Seen for the learner's Return and an agent'sreturnToCurrent, also on35e0215e. - Closes: the Return ends a test replay that is still opening (its marker, loading state and summary) and arranges Live at once; the open then changes nothing.
- Proof: host tests (learner and agent) red without the fix (
loading: true).
- Defect: the Return bumps
-
Found in this cycle (pt1 /ship review pass 2, state-machines): Reload pressed again after a same-study Reload whose load failed is refused. Fixed in
0a8d85de.- Defect: the 'reload-recording' action required
recordingActive; a Reload whose load failed before the recording was active kept its summary and its Reload button (task 18), which then threwSelect a recording first.; a second press while the Reload still loaded threw the same. - Closes: Reload works whenever the replay is shown (
browserReplayShown()), reloading the recording the replay last asked for (reloadShownRecording()). - Proof: host tests red on
40d30aa1.
- Defect: the 'reload-recording' action required
-
Found in this cycle (pt1 /ship review pass 2, Red Team): Retry and the Live tab ignore a same-study Reload's mark. Fixed in
0a8d85de.- Defect: during a loading or failed Reload, Retry storage / refresh ended in
renderSelection, drawing a Study selection under the browser replay's summary, and the 'tab' handler'swasRecordingreadrecordingActive, so choosing Live cleared the mark without re-arranging the reader. - Closes: Retry loads the recording again as Reload does; choosing Live re-arranges the reader into Live.
- Proof: host tests red on
40d30aa1.
- Defect: during a loading or failed Reload, Retry storage / refresh ended in
-
Found in this cycle (pt1 /ship review pass 3, state-machines and Red Team): a runtime release and a study deletion ignore a same-study Reload's mark. Fixed in
5bd1db27.- Defect:
retire()rendered the Study selection under the replay, andrecordingOpenOrOpening()allowed deleting the replay's study (which its Reload and Retry need), each because it readrecordingActivealone while a Reload was loading or had failed. - Closes: each reads
browserReplayShown(): the replay stays shown, and the deletion is refused with the Recording-open sentence until the learner leaves the replay. The Red Team's third item (the refresh's once-per-run Live entry) is evidence, no defect: that entry requiresselection.follow, which a recording's open sets false and only Return or the Live tab (both ending the mark first) set true again; a host test of it passed on0a8d85detoo. - Proof: host tests red on
0a8d85de.
- Defect:
-
Found in this cycle (pt1 /ship Step 11, Claude adversarial): nine suspicions checked against the code. Evidence (no defect) for seven of them; the first two (an Application pane write and its retitle during a Reload) proved real through Focus source and became task 37: a Reload's mark after a refused openRecording (the reader shows the failed replay with its Reload and Retry, as after a failed load); an entry ending a saved study's wait before it is refused (an explicit entry ends the wait as an explicit display does, task 15, and no browser replay can be shown during a wait); a rejected layout read in a saved-study choice (reported by reportFailedChoice, as showSavedStudy's own read is); Return clearing
loading(the Return supersedes every pending load it clears); pruneClosedTabRecord dropping two rebuilt entries of one address (only when no live tab shows that address, so none is left to close); the quiet STALE_PRESENTATION end (the identity changes only for a newer selection, a Return or a Close, each owning the summary); select() refused during a Reload (the intended task 28 refusal, for the command too). -
Found in this cycle (pt1 /ship Step 11, Codex adversarial and structured review, Claude adversarial F1/F4): six race and recovery defects in the new paths. Fixed in
40ecb542(L2 by evidence, below).- Defect: (L1) a failed or superseded earlier test replay open left the summary composition while a newer entry was entering it, so the newer replay opened without its summary and transport; (L2) a wait for the editor area that ended during its slot close could arrange a reader closed and reopened meanwhile; (L3) a refused close of the waiting slot tabs dropped their record, so no later display closed them; (L4) an entry superseded during its slot close still asked the one-replay-at-a-time notice and held the turn; (L5) a browser recording opened over a test replay whose read failed left the summary its placeholder, so its failure and recovery did not show (regression of task 2); (L6) a second Reload while the first still loaded started no load.
- Closes: (L1) only the last entry under way leaves an empty composition; (L2) the wait's end re-checks lifetime, choice and a new wait after its close; (L3) a refused close keeps the still-shown tabs recorded; (L4) the entry re-checks its ticket before the notice; (L5) the summary gets the reader's document again (giveSummaryItsDocument()); (L6) the Reload cancels the pending load first.
- Proof: host tests red on
5bd1db27for L1, L3, L4, L5, L6. L2 is evidence: two harness scenarios (Close + Open + a new wait, and a newer entry + a new wait, during the held slot close) did not arrange anything on5bd1db27either, because Close ends the timer refresh's signal before the stale wait end reaches open(); the re-check stays as a guard for refresh callers that pass no signal.
-
Found in this cycle (local CodeRabbit CLI round 11 on
40ecb542): the views read no recording during a same-study Reload. Fixed ina6a6a5d0.- Defect:
message()projectedrecording,model,contentTab,links,canClickandrunRefusalfromrecordingActivealone, so while a Reload loaded or after it failed the views got the browser family with no recording state (stale status, no failure) and the Live tab. - Closes:
message()readsbrowserReplayShown()for those fields; also in this round: the shared test fixturesaveOtherBrowserStudy, the JSDoc order ofclearLearningSummary, and README's Keep Tab Open exception. - Proof: host test (held and failed) red on
40ecb542(contentTab: 'live',recordingundefined).
- Defect:
-
Found in this cycle (local CodeRabbit CLI round 12 on
e177d0c6; Claude adversarial F2/F3): Focus source during a same-study Reload draws the Study selection in the Application pane. Fixed ine393b9f6.- Defect:
presentApplication()returned only whilerecordingActive; Focus source during a loading or failed Reload reached it throughrenderSelection, overwrote the replay's Application pane with the Study selection and renamed its tab. - Closes:
presentApplication()returns whilebrowserReplayShown(). - Proof: host test (held and failed) red on
e177d0c6.
- Defect:
-
Found in this cycle (N52 Cursor take 1 on
8e781153): leaving a browser replay paints "Loading recorded position…" in the Application pane. Fixed in270022c7; closes with N52 (e) on the new candidate. N52 evidence: noLoading recorded position…frame on (e) from a browser replay in Cursor take 3 (d7f5b0c0…) and VS Code take 1 (6737249e…) onfe37cce9.- Defect:
leavePlaybackcalledplayback.leave()beforedropReplayViewport(). The controller'shide()invalidated the shown moment, and the reader'sinvalidatecleared the still-open recorded viewport (clearRecorded, aresetwithclear), so the pane drewLoading recorded position…undercodebook · Recorded applicationfor 2 frames (67 ms) before the Live pane (take742da665…, frames 73–74 after the (e2) press at 154.39 s). - Closes: a departure releases the recorded viewport before the controller leaves, so the clear reaches no open viewport; a same-study Reload keeps the clear, which reads true there.
- Proof: host test (TB) red on
8e781153(['clear', 'close']), plus N52 (e) on the new candidate.
- Defect:
-
Found in this cycle (hosted CodeRabbit on PR v0.2.40.0 fix: replays leave, open and reload without stale frames, and their entries and exits behave as the learner chose (Cycle 0052, PR-1 of 3) #125,
studyWorkspace.ts:9157): a Reload refused after it left the replay drops the failed replay. Fixed in270022c7.- Defect:
reloadShownRecordingleft the playback and set the Reload mark beforeopenRecordingchecked its refusals. From the Reload buttonaction()checks them first, but Retry storage / refresh reads the storage before it reaches the Reload, so a presentation change begun meanwhile (an agent's restore) madeopenRecordingrefuse after the replay's failure and reason were gone and no load started. - Closes:
reloadShownRecordingchecksopenRecording's refusals (a pending presentation change, a study on its way to the Trash) before it changes anything; after themopenRecordingonly awaits the reader's finished initialization. - Proof: host test (TC) red on
8e781153(readinessidle, reason gone).
- Defect:
-
Found in this cycle (hosted CodeRabbit on PR v0.2.40.0 fix: replays leave, open and reload without stale frames, and their entries and exits behave as the learner chose (Cycle 0052, PR-1 of 3) #125,
studyWorkspace.ts:11919): Return to Live does not end an Open replay waiting for the work window's focus. Fixed in270022c7.- Defect:
enterSummaryCompositionForReplaywaited for the focus with no cancellation; a Return or Close bumped the entry ticket, but the wait went on for its 10 s bound, holding the next entry's turn. - Closes: each entry ticket has a cancellation that a newer entry, a Return or a Close aborts (
supersedeNodeHistoryEntries); the focus wait listens to it, and the overtaken entry ends quietly. - Proof: host test (TC) red on
8e781153(the entry still waiting after 5 s).
- Defect:
-
Found in this cycle (hosted CodeRabbit on PR v0.2.40.0 fix: replays leave, open and reload without stale frames, and their entries and exits behave as the learner chose (Cycle 0052, PR-1 of 3) #125,
studyWorkspace.ts:23435): two reads ofrecordingActivealone during a same-study Reload. (a) fixed in270022c7; (b) evidence below.- Defect: (a)
openReplyOwedTosetopensRecordingfromrecordingActive, so a Saved studies choice during a Reload or after it failed got its pane reply while the chosen recording still loaded; (b)shownReplayIdentitynames no replay during a Reload. - Closes: (a)
opensRecordingreadsbrowserReplayShown(). (b) evidence, no defect: a summary reveal outlasted by the Reload's load has run the summary's focus command, and the summary holds its document (the Reload keeps it), before the stale check ends it quietly (task 16); what it skips is the visibility wait, a redundant publish and Cursor's once-per-session Move View offer, which the replay's open already made. - Proof: host test (TC) red on
8e781153for (a) (the reply posted while loading).
- Defect: (a)
-
Found in this cycle (hosted CodeRabbit on PR v0.2.40.0 fix: replays leave, open and reload without stale frames, and their entries and exits behave as the learner chose (Cycle 0052, PR-1 of 3) #125,
README.md:19): README's Tracking named Cycle 0049 the active cycle. Evidence: docs diff in270022c7.- Closes: evidence: the Tracking list names Cycle 0052 (Cycle 0052: replays leave, move and open without stale frames, and every Cycle 0051 carried defect is closed #124) active and Cycles 0049–0051 closed with their pull requests; a docs-only diff.
-
Found in this cycle (N52 Cursor take 2 on
270022c7): leaving a browser replay redraws its Learning summary in a departing state for one frame. Fixed infe37cce9; closes with N52 (e) on the new candidate. N52 evidence: the summary goes from the replay's summary straight to its placeholder on (e) from a browser replay in Cursor take 3 and VS Code take 1 onfe37cce9.- Defect:
playback.leave()publishes while the summary still holds the replay's document. With the viewport released first (task 38), that publish drewThe current captured source is not ready in its native pane…andLoading the selected observation…for 1 frame before the placeholder (takeee8c00ab…, frame 73 after the press at 190.32 s). On8e781153the same publish reached the summary but drew no visible change. - Closes: a departure withdraws the Learning summary together with the recorded viewport before the controller leaves, so the leave's publish reaches no replay summary.
- Proof: host test (TC) red on
8e781153and on270022c7(twostudymessages reach the replay's document during the Return), plus N52 (e) on the new candidate.
- Defect:
-
Found in this cycle (hosted CodeRabbit review of
270022c7, outside-diff finding atstudyWorkspace.ts:11951): an Open replay entering from Live waits for the work window insideopen()without its entry's cancellation. Fixed infe37cce9.- Defect:
enterSummaryCompositionForReplaycalledopen()with no signal when it entered a new summary composition, soopen()'s wait for the work window before the summary's reveal (reached when the window loses the focus after the Application group was prepared; an entry that starts unfocused is refused at once) ignored a newer entry, a Return or a Close, and a newer Open replay waited up to 10 s for the earlier entry's turn. Task 40 covered only the standing composition's wait. - Closes: that branch passes the entry's cancellation to
open(); an overtaken entry ends quietly. - Proof: host test (TC) red without the fix (the first entry still waiting after 5 s; its layout response is held while the window loses the focus), plus two test changes reported in the PR: the four existing seams of
enterSummaryCompositionForReplayin TC forward the cancellation, and the two tests of an agent's Return that supersedes an entering entry assert that the summary holds no reader document instead of the placeholder (an entry superseded before itsopen()now builds nothing, so the summary is never touched); a mutation that removes the superseded entry's leave makes both fail.
- Defect:
-
Found in this cycle (hosted CodeRabbit review of
fe37cce9, outside-diff finding atstudyWorkspace.ts:11946): an overtaken Open replay's Learning summary reveal in the standing composition waits for the summary view. Fixed inc89e7dc2.- Defect: the standing composition's
showLearningSummarygot no cancellation, so its wait for the summary view held the next entry's turn up toPRESENTATION_READY_TIMEOUT_MS(5 s). - Closes: the reveal gets the entry's cancellation.
- Proof: host test (TC) red without the fix (the earlier entry still waiting at 2.5 s), green with it.
- Defect: the standing composition's
-
Found in this cycle (N52 VS Code take 1 on
fe37cce9): on (e) from a browser replay, the Application tab readscodebook · Recorded applicationfor one frame over the Live content. Evidence (no defect in the code):presentApplicationsets the title before it writes the document, in one synchronous call; VS Code painted the webview one frame before the tab strip (frames 58–59 of6737249e…), while Cursor shows both in the same frame (take 3, frame 32). The end state readscodebook · Applicationin both hosts. -
Found in this cycle (pt1 exact-HEAD gate on
c89e7dc2, health's coverage run): a Removal test read a queued archive write right after Stop. Fixed in4ddbb683(test timing): a save reports 'saved' before it writes the recording's context and leaves the queue; the fixture and two tests now read the queue after that. A 300 ms delayedsaveRecordingContextfails 9 of 204 Removal tests on26c4878c, none after; the line-retirement mutation fails the same two tests before and after.- Defect: in
studyWorkspaceRemoval.test.ts, "the line “History not saved: …” of a study whose capture failed and whose run this window no longer holds goes when Retry storage / refresh is pressed" readqueued: 1where0was expected in its first snapshot, taken right afteraction('stop')returns (fixturerecordRunWithFailedCapture). It passed in the same gate's test lane; neither the test nor the code it covers changed in pt1. Same family as tasks 26 and 27. - Closes: a root cause (the fixture reading the state before the Stop's queued write drains, or Stop returning before it) fixed with its test, or evidence from repeated health runs. Scheduled with tasks 26 and 27 (O1, pt3).
- Defect: in
-
Found in this cycle (local CodeRabbit round 2 on
f0c11ead): the Study pane's line of a refused test replay control still showed the storage path. Fixed in8a50e907.- Defect: task 21 sanitized
nodeHistoryRefusalonly;message().errorscarriedString(error)with the learner's storage folder. - Closes: that line loses the private roots and keeps its error name.
- Proof: host test (TC) red without the fix.
- Defect: task 21 sanitized
-
Found in this cycle (local CodeRabbit round 2 on
f0c11ead): a startup bound's closed-debugger error is worded as a start failure. Evidence (no defect).- The bound is
bounded(..., true)inReplayDebugger.awaitSession: its expiry is the replay debugger failing to start. Task 17 words that case with the restart clause. - After the expiry the owner reads
available === false, so the next selection goes throughreplaceUnavailableReplayDebuggerand restarts it. The clause is accurate. - A retirement's expiry is awaited outside the wrap and stays a moment failure.
- Round 3 on
8a50e907repeated the finding; checked again:expire()setsdetached, soavailablereads false, andpresentNodeHistoryDebuggerreplaces the owner before the next stop. No new finding in round 3. - Round 6 on
50408677(Minor,replayDebugger.ts:775) repeated it again; same evidence: the expiry is the start failing, and the next selection restarts the replaced debugger, so the restart clause holds.
- The bound is
-
Found in this cycle (pt2 /ship review, state-machines specialist): three recorded-source slot state cells were untested. Fixed in
f07e44cc(tests only).- Gap: slot-placeholder × leave to another moment; slot-loading × leave to another moment; slot-loading × commit of an output. The behavior was correct; no test held it.
- Closes: two host tests (TS): a move from an output to the result keeps the placeholder with no stop label and no reveal off line 1; after a failed show (F170's loading text), a move to an output replaces the loading text with the placeholder from line 1, with no stop label.
- Proof: each test is red under a temporary mutation (the placeholder revealed at line 2; a label drawn for a slot without a stop), green without it.
-
Found in this cycle (pt2 /ship review, Red Team and state-machines): four suspicions checked against the code. Evidence (no defect) for each:
- (a) A closed debugger's expiry worded as a start failure: the same finding as task 49, same evidence.
- (b) CHANGELOG's 0.2.38.0 entry still names the slot's CodeLens: each entry describes its own version; this version's entry (the pt2 release commit) states that the tab draws no CodeLens, and
NODE_HISTORY_LEAVE_SETTLE_MS's comment says the lens is gone. - (c) Other Study pane lines (
control,archive, …) still carry full local paths: README's Output › Codebook paragraph documents that some messages can still show full local paths; tasks 21 and 48 align the test replay control's two lines with the replay's other failure lines. Sanitizing every line would change unrelated features, an increment outside a bug-fix cycle. - (d) Repeated entries stack identical one-replay-at-a-time notices with dead Close buttons: VS Code's
NotificationsModel.addNotificationcloses an equal earlier notification ("Deduplicate",src/vs/workbench/common/notifications.ts; equal = source, message and primary actions, whose ids are_extension_message_handle_<index>permainThreadMessageService.ts), and the closed notice's promise resolvesundefined, so one notice shows and the earlier entry ends quietly (task 11). Cursor runs the same workbench model; not observed natively there.
-
Found in this cycle (pt2 /ship Step 11, Claude adversarial): a refused test replay control's line shows the storage path after a runtime release. Fixed in
ec479ab8.- Defect: tasks 21 and 48 sanitized the line at publish with the service's roots;
retire()clearsthis.service, so any later publish had no roots and showedString(error)with the learner's storage folder on the transport's status line and the Study pane's line. - Closes:
report()stores that kind with the roots replaced while the service names them;message()publishes the stored line (the transport's copy without its error name). - Proof: host test (TC) red on
f07e44cc, green after.
- Defect: tasks 21 and 48 sanitized the line at publish with the service's roots;
-
Found in this cycle (pt2 /ship Step 11, Claude adversarial): six further suspicions checked against the code. Evidence (no defect) for each:
- (a) The slot's whole label is no longer reachable without a mouse: O8; the Call Stack thread
Recorded test stop <n> · <path>:<line>and the transport readout carry its path, line and time to keyboard and screen-reader users. - (b)
withoutPrivateRootsstrips a nested error name:withoutErrorNameremoves one anchored leading name only, soError: TypeError: xstays whole. - (c) A start failure and an abort in the same tick: the move was overtaken, and the newer selection words its own outcome; otherwise task 49.
- (d) A late Close on an overtaken notice after a Return: Return and Close call
supersedeNodeHistoryEntries()(tasks 12, 40), anduntilAborteddrops its listener when the notice settles. - (e) The placeholder reveal yanks a learner's scroll: it runs only when the slot's text becomes the placeholder at a commit, where F204's reveal already puts line 1 at the top; the order was checked natively in N52 (b).
- (f) A repeated Show more open token: it is
++historyRequest, which only grows per reader, and the webview's state ends with the window.
- (a) The slot's whole label is no longer reachable without a mouse: O8; the Call Stack thread
-
Found in this cycle (pt2 /ship Step 11 Claude adversarial pass 2, and the Step 9 delta review): causes worded after a runtime release had no private roots. Fixed in
afdf3fac.- Defect: the reader keeps serving its history store after
retire()clears the service, but its 11 sanitizing sites fell back to{ storage: [] }(Save Learning Replay's notice to the home directory alone), so a control refused after the release, or a failure worded then, showed the storage folder or workspace. - Closes:
privateRoots()gives the attached service's roots, after a release the released service's (remembered inretire()), before any service the roots the reader holds itself; every site uses it. - Proof: two host tests (TC) red on
ec479ab8, green after.
- Defect: the reader keeps serving its history store after
-
Found in this cycle (pt2 /ship Step 11 Claude adversarial pass 2): six further suspicions. Evidence (no defect) for each:
- (a) An overtaken notice's Close button does nothing: after a Return or a Close the browser replay it names is no longer shown, an extension cannot withdraw its own notification, and a newer entry's equal notice replaces it (task 51 d); README and task 11 state that an earlier notice's answer closes nothing.
- (b)
Error: Error: xloses a name: the stored line keeps both (withoutPrivateRootsputs back the onewithoutErrorNameremoved), and the transport drops one, as before pt2. - (c) Roots that change later: the stored line already reads
<storage>,<workspace>or~; no old path is kept. - (d) A hidden slot tab keeps a stop's scroll: a tab that is not visible has no editor to draw a header, and it lays out the placeholder's bytes when shown; N52 (b).
- (e) A disposal or retirement worded as a start failure:
startingrejects only with the launch's failure or the startup bound's expiry; a disposal resolves it, and a retirement is awaited first (retiring). - (f) A permanent failure told to retry: the sentence is task 17's specified wording for every failure other than the debugger's start; a source that does not verify shows the 4A placeholder, not a failure.
-
Found in this cycle (local CodeRabbit round 5 on
dba70b06, Major + Minor): a failed move says "The last moment is still shown." when the return to it failed too. Fixed in50408677.- Defect: after a failed presentation,
returnToCommittedNodeMomentcould not show the committed moment (the slot failed to open, or it threw), and the line still claimed it was shown; a return overtaken by a newer selection also reported the old move's refusal. - Closes: the return reports
returned,supersededornot-shown; the line keeps "The last moment is still shown." only afterreturned, an overtaken return reports nothing (DS-F), and the recorded-source row tells a failed return. F368's test expectation is restated (its return throws). - Proof: host test (TC) red on
dba70b06, green after.
- Defect: after a failed presentation,
-
Found in this cycle (hosted CodeRabbit on PR v0.2.41.0 fix: Cycle 0052 pt2: a test replay's moves, notices and summary page #126,
replayDebugger.ts:779):ReplayDebugger.available's JSDoc said only a replay reopen replaces an unavailable owner. Fixed in9d85bebc(docs).- Defect: the doc omitted that an explicit selection or Inspect of a test replay's stop replaces it too (
presentNodeHistoryDebugger→replaceUnavailableReplayDebugger), which led reviewers to read the move's restart clause after a startup expiry as wrong (task 49's finding, a fifth time). - Closes:
availableandawaitSession's@throwsname the expiry, which selections replace the owner, and that a seek or Play never does. Proof: evidence, a comment-only diff; the branch is covered bystudyWorkspaceTestReplayCells.test.ts:807.
- Defect: the doc omitted that an explicit selection or Inspect of a test replay's stop replaces it too (
-
Found in this cycle (pt2 exact-HEAD gate on
50408677, health's coverage run): a configured-service test timed out under coverage. Fixed inadb6e2d0(test bound): nine release waits useRUN_RELEASE_BOUND_MS(10 s), not 1 s. A release delayed 1.5 s fails those nine on26c4878cand none after; afailByReleasethat leaves no error fails the task's test 3/3, before and after.- Defect:
configuredService.test.ts, "a completed run whose release failed after its saved study was removed by hand names the failed write and the removal as its error, and no storage path", hitTimed out waiting for the failed release of the completed run(itswaitUntilbound) only insidepnpm health's instrumented run; it passed in the same gate's test lane and in CI. Same family as tasks 26, 27 and 47. - Closes: a root cause (a wait bound too short for instrumented runs, or the code) fixed with its test, or evidence from repeated health runs. Scheduled with tasks 26, 27 and 47 (pt3).
- Defect:
-
Found in this cycle (pt3, task 22's failed-open cell): a browser replay whose open failed wrote no Output › Codebook entry. Fixed in
26c4878c.- Defect: a test replay's failed open writes an
open:test-replayentry for a report; a browser replay's (openLearningReplay) showed its notification only, so task 22's contract ("one Output › Codebook entry") did not hold. - Closes: the failure also writes one
open:recordingentry with the study, the profile and the sanitized cause; the README says so. - Proof: host test (TB) red before the fix (
outputEntries: []).
- Defect: a test replay's failed open writes an
-
Found in this cycle (N52 pt3, VS Code): a node-history reference to an unknown study id answered
RUNTIME_FAILEDwith a rawENOENT. Fixed inaff71ba9.- Defect: Copilot Chat sent
…-4735-…for…-473e-…in a history's id;codebook://node-history/<id>/learning-materialanswered "The study operation failed." with the store'sENOENT: lstat '<storage>/node-tests.v1/<id>'and a recovery about owned resources and clicks. - Closes: the node-history resources and
codebook_explain_node_historyrefuse an id with no history folder asNOT_FOUND, naming the id andcodebook://node-history; README says so. - Proof: host test (
nodeHistoryResources.test.ts) red without the fix (rawENOENTfor all three calls).
- Defect: Copilot Chat sent
Tasks 61+ continue in this comment (the body is near GitHub's size limit).
Native round N52 (both hosts)
N52 runs in the Space local:codebook-qa on nextjs-dashboard at 1936e41, at the D034 layout (PRODUCT_GOAL.md, Product constraints: an ordinary desktop display, the editor window expanded, default zoom). It uses each PR's candidate VSIX before that PR merges. The Space's OBS setup and preflight are in AGENTS.md (Native QA). Each PR runs only its own checks:
- pt1: (d), (e), the Application title, the empty group.
- pt2: (b).
- pt3: the live checks.
Hosts and chats:
- VS Code: Copilot Chat, GPT-6 Luna.
- Cursor: Agent, Grok 4.6 High (Fast allowed).
- Fallback: the installed Codex Extension after observed credit exhaustion.
Each host gets a new natural /codebook question about a nextjs-dashboard code path that #107, #118 and #122 did not ask, frozen in a comment before submission.
Checks, in each host:
- (b) moves (task 1): from a saved test replay, press Next stop, Previous stop, Next event (output, then result), Previous event, Replay from start, a slider seek, ArrowRight and Home on the slider, and Play. In no frame does a pending move show the previous stop's CodeLens label or the old source's sticky-scroll header.
- (d) browser open (task 6): open a saved browser replay with Open replay (a browser study recorded in that host if none exists). No frame shows Study content in the Learning summary before the replay's summary. The transport has no event buttons.
- (e) Return to Live (tasks 2, 3, 6): run Codebook: Return to Current Pause from a test replay, then from a browser replay. No frame shows Study content in the summary or a test-family transport (
Test journal playback). The end state is the Live composition with the Study pane closed and the summary placeholder. - Application title (task 4): after (e) from the browser replay, the Application tab reads
codebook · Application. - Empty group (task 24): no empty editor group in the test replay composition.
- Live (tasks 5, 7, on pt3):
- The question reaches a value the earlier run could not read; if it does not, the result is NOT RUN with the reason.
- A browser run to a page's link reaches a stop in the launched route, or receives the new refusal sentence.
Validity across PRs. If a later PR changes code that an earlier PR's native check covered, that check runs again on the later PR's candidate. The cycle closes on native evidence from the final candidate for every check.
Task 5 natively. The unit and runtime tests are task 5's proof. The native check is an observation: NOT RUN there does not hold the task.
Measurement. OBS Window Capture at 30 fps; the saved file's frame rate is verified. For each transition, every native frame is inspected from the press to 1 s after the last pixel change. One take per transition per host, with the press time logged. A claim covers recorded frames at 30 fps only, not sub-frame timing. A dropped or frozen frame voids that take, which is taken again.
Acceptance criteria
-
Each task is checked with "fixed in " and its test, proven as its kind requires (Tasks, above), or with "evidence: " where its Closes line allows evidence (tasks 6, 7, 9, 23, 24).
-
Each new or changed test states
protects=…; fails_when=…; no_claim=…. The card goes in its Value line for a Reader DOM case, as the existing cases do, or in a comment above the test for a host test. -
N52 passes in both hosts as above, with each take's SHA-256 recorded in this Issue.
-
The 15-check exact-tree gate passes on each PR's final tree:
- from
extension/:pnpm format:check,pnpm typecheck,pnpm lint,pnpm health:static,pnpm dupes,pnpm dead-code,pnpm test; - from the repository root, after that build:
node extension/scripts/<check>-qa.mjs verify <new empty folder>for each ofstudy-bootstrap,wiki-reader-dom,study-reading-pose,understanding-focusandrepository-return; - from
extension/:pnpm test:package, thenpnpm health; - from the repository root:
node --test .codex/restore-product-context.test.mjs.
Required CI passes on the exact head, and hosted CodeRabbit APPROVES that head before the merge.
- from
-
Each user-visible change has a CHANGELOG entry and its sentence in
extension/README.md. -
No existing test is weakened. Any changed test, validator, timeout or threshold is reported with its reason in the PR.
Rules for the implementing agent
- Acceptance criteria are each test's
protects / fails_when / no_claim. Never "make the tests pass". - Real code and real tests land together.
- Any change to a test, validator, CI step, timeout, tolerance, threshold, snapshot or suppression is reported on its own line with its reason.
- A reported command names the command and its observed result.
- A report is a claim until the driving agent re-executes it.
Rollback, out of scope
Rollback: revert the PR. No stored format or MCP contract changes. MCP stays 1.8.
Out of scope:
- Any new run profile or increment. Package-root Vitest and new profiles stay later candidates (Cycle 0051: a test replay opens in the region-2 composition, with the Learning summary in the chat's place, one transport and 5A #122 Owner decisions).
- The later candidates C1, C5, C8 to C12, E8 and E9.
Owner decisions
-
Standing:
- The owner's goal of 2026-10-24 (Cycle 0050: every defect Cycle 0049 carried is fixed or closed with evidence #118), and the direction of 2026-10-22: devote every resource to the product; never spend money or break the law.
- The owner cannot answer, so each decision point takes the recommended option, named here.
-
O1 (recommended,
/spec): delivery in up to three PRs, merged in order. Each passes its own reviews, CI and gate.cycle-0052-pt1: departure and summary lifecycle (tasks 2, 3, 4, 6, 12–16, 18, 24).cycle-0052-pt2: moves and summary page (tasks 1, 11, 17, 19–21).cycle-0052-pt3: live runtime and hygiene (tasks 5, 7, 8, 9, 10, 22, 23).
Each PR runs its own N52 checks before its merge (Native round, above). Considered: one PR, which would carry 24 tasks into one /ship review limit of three rounds.
-
O2 (recommended,
/spec): tasks 5 and 7 start with/investigate. Their root cause is recorded in this Issue before code moves. Considered: patching the symptom (catching the error), which could hide a capture gap. -
O3 (recommended,
/spec): no/spec --executeagent. The driving agent owns the cycle and runs every native trial. It may hand a bounded implementation part to a subagent under its review; a subagent never moves HEAD. -
O4 (recommended,
/spec): task 5's refusal uses the existingEVIDENCE_UNAVAILABLEcode and keeps the run paused. MCP 1.8's schema is unchanged. Considered: keepingRUNTIME_FAILED, which ends a run the agent could continue. -
O5 (recommended, pt1
/ship): the gstack upgrade offered at/ship's start waits (Not now). Changing the skill install mid-ship would change the instructions under a running workflow. -
O6 (recommended, pt1
/shipStep 9): every ASK finding is fixed (tasks 28, 29 and the untested state cells get host tests); the two simplification advisories (redundant waiting-record resets inclose()andshowStudyAwaitingEditorArea) are kept as harmless defensive resets, as the specialist recommended. Low-confidence appendix items (sanitizing the editor's tab-close error, an entry's reveal failure, the Reload mark's study id after another failed open) were checked and recorded in the PR as by design. -
O7 (recommended, pt1
/shipStep 9): a saved-study choice during a same-study Reload opens the chosen recording, and a step selection is refused until the recording has loaded again (task 28). Considered: letting the choice supersede the Reload and return to the Study composition, which would make a failed Reload behave unlike the replay it still shows. -
O8 (recommended, pt2, task 1): the recorded-source slot draws no CodeLens.
- The editor redraws a provider's lens only after its own refresh delay (at least 250 ms in VS Code, about 300 ms in Cursor), so any lens names the stop a move left beside the next moment, for frames of every move. A pending lens would be just as stale.
- The end-of-line label and its hover carry the whole label, which also appears in the Call Stack thread and the transport time.
- The v9 replay region draws no label line above the code (checked on the PNG, 2026-10-25).
- Considered: keeping the lens (F207's whole label in narrow groups) and accepting the stale frames, which task 1's Closes line forbids.
-
O9 (recommended, pt2
/shipStep 8): the plan audit's one UNVERIFIABLE item (task 1's native proof) counts as verified. The driving agent checked N52 (b)'s takes (Cursor take 2380d57ee…, VS Code take 1e2166ac6…) and the candidate VSIX1976136d…against the hashes recorded here. -
O10 (recommended, pt2
/shipStep 9): the simplification advisory is kept as is.withoutPrivateRootsandpublishedNodeHistoryRefusalpublished two forms (with and without the error name) for two surfaces; the sharedcauseRootsfallback recurs at six other call sites, a file-wide refactor outside a bug-fix cycle. (Task 52's fix later removedpublishedNodeHistoryRefusal, so one helper remains.) The RH-1 test removals (the slot's CodeLens tests, F207, F367, F373) are justified by O8's removal of the lens in the same diff, so Gate Integrity has no finding. -
O11 (recommended, pt2
/shipStep 9): the review's repeat after the test-only fix (f07e44cc) reviews that delta. The product code is unchanged since the full review (seven specialists, Red Team, exploratory QA); a whole second pass would add nothing to the product (owner rule of 2026-10-22). -
O12 (recommended, owner rule of 2026-10-23): pt2's /ship review stops at its third fixing cycle with
converged:false. Cycle 3 (afdf3fac, task 54) fixed every finding of the last round; no Critical or Major finding stays open, so no Issue is filed. The final delta was reviewed by the cycle-3 delta review; the local CodeRabbit CLI and hosted CodeRabbit (no round limit) review the final head before the merge. -
O13 (recommended, owner rule of 2026-10-22): no third documentation audit for pt2. /ship allows two audits; both ran (
c52-pt2-docs-192447,c52-pt2-docs-193203). Task 56 then added one README sentence and one CHANGELOG sentence for its own fix. Local CodeRabbit (the.coderabbit.yamlCHANGELOG → README rule) and hosted CodeRabbit check them; a third audit would add nothing. -
O14+ continue in the same comment.
Next action
Closed. pt1 d4ecc320 (v0.2.40.0), pt2 83f9128e (v0.2.41.0), pt3 83a07385 (v0.2.42.0, PR #127). Nothing is carried; the next cycle is a feature cycle, written by /spec and designed through /autoplan from PRODUCT_GOAL.md and a new gap audit.
Activity
ryota-murakami commentedon Oct 24, 2026
Entry (2026-10-24, planning)
docs/designs/assets/codebook-product-spec-v9.png: 1,878,402 bytes, SHA-256f189ee82541a72ed981e3f7a0e21bd35a19b6601df1c7208671117a335caf2aa, which matches the Design target. Regions found:codex/cycle-0052atbd082540(origin/main, v0.2.39.0). The tree is clean, and no PR is open./specwrote this Issue from Cycle 0051: a test replay opens in the region-2 composition, with the Learning summary in the chat's place, one transport and 5A #122's closing comment, with one task per carried defect. The Codex quality gate scored it 8/10 after one revision.cycle-0052-pt1(O1).ryota-murakami commentedon Oct 25, 2026
Re-entry after compaction (2026-10-25, implementing pt1)
b3aae89a…).docs/designs/assets/codebook-product-spec-v9.pngopened with an image tool: 1,878,402 bytes, SHA-256f189ee82541a72ed981e3f7a0e21bd35a19b6601df1c7208671117a335caf2aa(matches the Design target). Regions: 1 live (chat beside app, stopped source, native debugger, bottom capture status), 2 replay (Learning summary in the chat's place, one transport), 3 DeepWiki, the shortcut strip.codex/cycle-0052atc03cc15b(local CodeRabbit round 8 fixed: Open replay into a standing summary composition waits for the work window before its reveal; a superseded entry leaves the composition only outside a Return or presentation change). Clean tree; no PR open. Workspace partitions: 2054/2054 pass onc03cc15b.c03cc15b, then/shipfor pt1.ryota-murakami commentedon Oct 25, 2026
pt1 shipped as PR #125 (2026-10-25)
8e781153. /ship ran its three fixing cycles and Step 11's adversarial reviews: converged:false; every last-round finding is fixed, so no Critical or Major defect stays open and no follow-up Issue was needed (owner rule 2026-10-23).pnpm test6762 pass / 0 fail;pnpm test:package1061 pass / 0 fail; pre-gate Stage 1 PASS; local CodeRabbit CLI round 13: 0 findings. The exact-tree gate on032a5209passed 14 of 15; its package lane failed only on the missingEXTENSION_VERSIONbump, fixed in8e781153./coderabbit-resolver), N52 pt1 in both hosts, the exact-HEAD gate, merge.ryota-murakami commentedon Oct 25, 2026
Re-entry after compaction and N52 Cursor take 1 (2026-10-25, validating pt1)
docs/designs/assets/codebook-product-spec-v9.pngopened with an image tool: 1,878,402 bytes, SHA-256f189ee82541a72ed981e3f7a0e21bd35a19b6601df1c7208671117a335caf2aa(matches the Design target). Regions: 1 live, 2 replay (Learning summary in the chat's place, one transport), 3 DeepWiki, the shortcut strip.codex/cycle-0052at8e781153(PR v0.2.40.0 fix: replays leave, open and reload without stale frames, and their entries and exits behave as the learner chose (Cycle 0052, PR-1 of 3) #125 head), clean tree; CI green on that head; hosted CodeRabbit CHANGES_REQUESTED (4 Minor threads, no outside-diff finding).N52 pt1, Cursor, take 1 (candidate
8e781153)local:codebook-qa, Cursor with Codebook 0.2.40 fromcodebook-0.2.40.0-8e781153.vsix,nextjs-dashboardat1936e41, window 1920 × 1050. OBS Window Capture of the Cursor window after a passing preflight.742da665421ca7afb835b39f06111ff0a33b737cfd6b09e7d6110aafbf9ee9f1, equal in the Space and on the Mac (privateartifacts/cycle-0052/n52/cursor/). Every native frame inspected from 2 s before each press to 6 s after it.Test replay paused, its 20.56 s / 45.37 s history) to the Live Study page, with noTest journal playbackframe. End state: Live composition, Study pane closed, summary placeholder.LoginForm callbackUrl and submit controls), with no frame of Study content; the transport shows no event buttons. Route: the Study pane's Recording tab, which calls the sameopenRecordingload as the status bar's Open replay (that item appears only after a save in that window).Loading recorded position…undercodebook · Recorded applicationfor 2 frames (73–74) before the Live pane.codebook · Applicationfrom frame 75 on).actions.tswithCaptured-actions.ts; the learner's tabs).270022c7change the departure path, so every pt1 check runs again in both hosts on the new head's candidate.ryota-murakami commentedon Oct 25, 2026
N52 pt1, Cursor, take 2 (candidate
270022c7)codebook-0.2.40.0-270022c7.vsix(SHA-256fae712fa6a513a5d130421d175e940c9bcd9d6856f88337d5365c3b260e4de79), installed in both editors' QA profiles; the installeddist/extension.jsmatches the VSIX (5cf8bdc6…); Cursor reloaded before the take. New OBS preflight after the relaunch: 33.4 s, 30 fps, SHA-256389d720595123cd16bc5338c55bf1ed0a43da3b0b78e2bd255e4bf7a1f29d84f. It records only the Cursor window while OBS and then Safari are in front. A bottom-panel toggle paints, and the audio is silent (−91 dB).ee8c00abfae26c1d91577d42392233456372b4c6600c3caeebfb51b66d6c81b8, equal in the Space and on the Mac. Every native frame inspected around each press.No application frame was received at this position.until the Live pane at frame 76, with noLoading recorded position…frame. The title readscodebook · Applicationfrom frame 76 on.The current captured source is not ready in its native pane…,Loading the selected observation…) for one frame before the placeholder.ryota-murakami commentedon Oct 25, 2026
N52 pt1 results on candidate
fe37cce9(both hosts)Candidate.
codebook-0.2.40.0-fe37cce9.vsix:cb3c43bebdc7a38146ab2ee7b60c9bbf422efc11cf0a867f5bef60f2a17a6e29.dist/extension.jsreadse96464868cd2…in both editors' QA profiles.Setup. Space
local:codebook-qa,nextjs-dashboardat1936e41, window 1920 × 1050, default zoom. Recording used OBS Window Capture of the exact QA window, after a passing preflight per host. Every native frame was inspected around each press. Originals are private, underartifacts/cycle-0052/n52/.Cursor (Agent's window, Grok 4.6 High profile)
d7f5b0c0980762a22fbc2e26d06486feaa645022b410080feee05a1dc7c38aa6, equal in the Space and on the Mac.Test journal playbackframe.Loading recorded position…frame (task 38) and no departing summary (task 43).codebook · Applicationfrom frame 32 on.VS Code 1.142.0 (profile
Codebook QA 0049)aa50fc03fe34ce48294da19d45b70c8710397f4f2cf8c290846fc553982ac85a. It records only the VS Code window with Safari in front, a panel toggle paints, and the audio is silent.6737249e3c3954942d3241ff6114cee19d2c807ccb34b1f925fc378aec9842bb, equal on both sides. It used its own saved studies: test replaye763a398and browser studyd23c7d89.codebook · Applicationat the end. Frame 58 shows the Live content under the old title for one frame; recorded as task 46 (evidence, no code defect).Validity for
c89e7dc2.c89e7dc2adds only task 45: a cancellation for the summary reveal of an Open replay into a standing composition. The changed code is the one call inenterSummaryCompositionForReplay's standing-composition branch. No pt1 native check enters that branch:So these results carry over to
c89e7dc2on that ground.v0.2.40.0 fix: replays leave, open and reload without stale frames, a…
ryota-murakami commentedon Oct 25, 2026
pt1 merged (2026-10-25)
PR #125 merged as squash
d4ecc320(v0.2.40.0), pinned with--match-head-commit c89e7dc2fa665d7887d93e465295359aae0d4c89.Merge conditions on that exact head:
check-ci-status.shpassed.fe37cce9, valid forc89e7dc2(comment above).pnpm healthpassed on a lone rerun after one Removal test failed inside its coverage run (task 47, pt3).Fixed after /ship: tasks 38–46, each with a host test red before its fix, or closed by evidence (41b, 42, 46).
Carried within the cycle (O1):
Next: pt2 on
codex/cycle-0052-pt2.ryota-murakami commentedon Oct 25, 2026
N52 pt2 (b), Cursor, take 1 (candidate
75dec02f)Candidate and setup.
e6a093e19a5b0534abf8e3d3fc96f1bc9aea54454e70417b54b14bb85e0c391d;extension.jsb952a797…in both editors.656dadcd…passed: Window Capture of the QA window, the panel toggle paints, Safari stays out, silent.Take.
13b9c07b3ccad37a2eec671a474638bdce6bd8ce957dc3d788d267b31fb3a8c0, equal on both sides.c1dc77fc(2 stops inapp/lib/actions.ts, 45.37 s). Moves: Next stop, Previous stop, Next event ×3 (stop 2 → output → result), Previous event, Replay from start, a slider seek, ArrowRight and Home on the slider, Play to the result.Results.
Recorded: app/lib/actions.ts:<line> · <t> s, and the leave clears both in one frame.f0c11ead.27 export async function authenticate(for 11 frames, until the commit's reveal at 90.17.Next: take 2 in Cursor and a VS Code take on the
f0c11eadcandidate.ryota-murakami commentedon Oct 25, 2026
N52 pt2 (b) on candidate
f0c11ead, both hostsCandidate.
codebook-pt2-f0c11ead.vsix: SHA-2561976136dc1e28b26b77b5fe8e6c26a9f91d816c61e178f7ea087725a0f83c1cc; the installeddist/extension.jsreadsc95888d4947e…in both QA profiles; each window was reloaded first. 30 fps OBS Window Capture after a passing preflight per host. Every native frame of each stop → output transition was inspected; the other moves were checked at 10 fps. Originals are private, underartifacts/cycle-0052/n52-pt2/.Cursor, take 2
Take. 122.9 s, SHA-256
380d57ee55bc3359cb3062c9066469414d0c0d6ddb24ea7ec090e7fdfbc76165, equal on both sides.Moves. Replay
c1dc77fc, reopened at its saved result. Previous stop, Next event ×2, Previous event, Replay from start, Next stop, a slider seek, ArrowRight, Home, Play.Results.
export async function authenticate(.VS Code 1.142.0, take 1
Preflight. SHA-256
dd040972568fb5244f43b8bba5c3dd42160894ffe008cb9563f7722bb5f5c02f.Take. 172.3 s, SHA-256
e2166ac64f39432ad31130133546db53dc1d720eb8818145d57007c42ca4f6a0, equal on both sides.Moves. Replay
d05f8c73(3 stops inapp/lib/data.test.ts), so the replay differs from Cursor's. Previous stop ×2, Next stop, Next event ×3, Previous event, Replay from start, a slider seek, ArrowRight, Home, Play to the result.Results.
Verdict. N52 (b) passes in both hosts on
f0c11ead. Task 1 is closed by75dec02fandf0c11ead, with these takes.ryota-murakami commentedon Oct 25, 2026
Re-entry after compaction (2026-10-25, pt2 /ship Step 9)
docs/designs/assets/codebook-product-spec-v9.pngopened with an image tool: 1024 × 1536, 1,878,402 bytes, SHA-256f189ee82541a72ed981e3f7a0e21bd35a19b6601df1c7208671117a335caf2aa(matches the Design target). Regions: 1 live (chat, app, stopped source, native debugger, bottom capture status), 2 replay (Learning summary in the chat's place, one transport, 4A gap caption), 3 DeepWiki (Update LLM Wiki, output, Open in VS Code), the shortcut strip.codex/cycle-0052-pt2at8a50e907; one uncommitted test (the Step 7 coverage audit's abort case inreplayDebugger.test.ts)./shipfor pt2 is in Step 9 (review army); no PR yet.ryota-murakami commentedon Oct 25, 2026
pt2 /ship done: PR #126 open (2026-10-25)
v0.2.41.0, head50408677, Refs Cycle 0052: replays leave, move and open without stale frames, and every Cycle 0051 carried defect is closed #124.converged:falseat the ship review limit (O12).bd938d35). Round 5: task 56 (50408677). Round 6: a repeat of task 49, closed by its evidence.f0c11ead. The later commits change cause wording, sanitizing and tests, not the slot, the reveal or the lens, so (b) carries over on that ground.50408677(running), required CI, hosted CodeRabbit APPROVED on the exact head via/coderabbit-resolver, then the merge with--match-head-commit.docs: ReplayDebugger.available and awaitSession say which selections …
v0.2.41.0 fix: Cycle 0052 pt2: a test replay's moves, notices and sum…
8 remaining items
ryota-murakami commentedon Oct 25, 2026
Re-entry after compaction (2026-10-25, pt3 /ship Step 9 pass 3)
b3aae89a…).docs/designs/assets/codebook-product-spec-v9.pngopened with an image tool: 1024 × 1536, 1,878,402 bytes, SHA-256f189ee82541a72ed981e3f7a0e21bd35a19b6601df1c7208671117a335caf2aa(matches the Design target). Regions: 1 live (chat beside the app, stopped source, native debugger, bottom capture status with Save learning replay), 2 replay (Learning summary in the chat's place, one transport, 4A gap caption), 3 DeepWiki (Update LLM Wiki, output, Open in VS Code), the shortcut strip.codex/cycle-0052-pt3at3e165538, clean tree, no PR yet./shipStep 9 has run two fixing cycles (tasks 61–66); pass 3 reviews the delta114f13f6..3e165538, and its specialist findings are in.ryota-murakami commentedon Oct 25, 2026
pt3 /ship done: PR #127 open (2026-10-26)
v0.2.42.0, head16623fa2, Refs Cycle 0052: replays leave, move and open without stale frames, and every Cycle 0051 carried defect is closed #124.converged:falseat the ship review limit (O17, O18). No Critical or Major finding is open, so no Issue is filed.current, then one README sentence); no third (O20).550b5ec0; they carry over (O19).16623fa2(running), required CI, hosted CodeRabbit APPROVED on the exact head via/coderabbit-resolver, then the merge with--match-head-commit.fix: hosted CodeRabbit review of 16623fa (Cycle 0052 tasks 81-85)
fix: a history page whose history is removed while its summary is rea…
fix: an import written in a comment or a string binds no name (Cycle …
fix: nested templates and quoted export names in a stopped file's imp…
fix: CRLF string continuations and a history removed after its summar…
fix: line separators in strings, and three Removal tests read the rem…
fix: a history's material removed right after it was read is NOT_FOUN…
fix: every history read checks for a removal after it answered (Cycle…
fix: an imported name is read only from its own declaration's module …
fix: a stop's imports are read from the bytes the capture verifies (C…
v0.2.42.0 fix: Cycle 0052 pt3: a live test run survives a value it ca…
ryota-murakami commentedon Oct 25, 2026
Cycle 0052 closed (2026-10-26)
Outcome: demonstrated. Every defect Cycle 0051 carried (tasks 1–24) is closed, and every defect found in this cycle (tasks 25–97) is closed by a fix with a test red without it, or by recorded evidence. Nothing is carried. The next cycle is a feature cycle (
/spec, designed through/autoplan).Delivery (three PRs, merged in order, O1):
d4ecc320(v0.2.40.0).83f9128e(v0.2.41.0).83a07385(v0.2.42.0), merged with--match-head-commit 06291932. The merged tree043f9ae2equals the verified head's.pt3 merge conditions on
06291932:pnpm health: exit 0.check-ci-status.sh: exit 0.06291932, with 0 unresolved threads. Every outside-diff finding of every review is dispositioned (tasks 86, 87, 90, 94–97).043f9ae2).converged:falseat the ship review limit (O17, O18). No Critical or Major defect stayed open, so no Issue was filed.Native round N52, both hosts:
fe37cce9.f0c11ead.550b5ec0.06291932.sourceImportBindingsgives the bindings the N51 probe saw:db(actions.test.ts→__vi_import_3__, hoisted) andusers(data.ts→__vite_ssr_import_2__).nextjs-dashboardat1936e41). Both reads therefore resolve as before.Later candidate increments (at most one, per AGENTS.md): none recorded here. The next feature cycle is chosen by
/specfrom PRODUCT_GOAL.md and a new gap audit.