Repository navigation
Conversation
The tree, the /graph payload and summary --json already said where a history forked, not why. Each branch's first node is now compared with the earlier sibling it should have matched, and the difference is named: resample, edited reply, re-rendered, different message, or tools or model, with the fields that changed. The tree shows it as a badge on that node, /graph carries it as the node's fork, and summary adds fork_kinds to the stats so a harness can be gated on the kind of fork it made, not only on forked == 0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Names the cause of each fork in a skycap record, in the Tree, in
/graphand insummary. TLDR: the viewer already says where a history forked; this says why.This is the part of NovaSky-AI/SkyRL#2440 (
skycap check) that the viewer did not already cover. That PR was closed with the suggestion that this inspection belongs here rather than in skycap; theforkedflag, the branch points andsummary --jsonalready cover the rest.How it works
Each branch's first node is compared with the earlier sibling it should have matched, and the difference is named:
resample: the model replied again to a history it had already answerededited reply: the harness sent back a model reply with fields changed (e.g.reasoning_content dropped)re-rendered: token mode, the same message rendered to different tokensdifferent message: a compaction, a subagent, a rewritten turntools or model: the same message sent with another tool set or model, which starts a new rootsrc/forks.jsreads the document alone, walks only the roots and branch points, and normalizes messages the way skycap's match hash does (every field in text mode, the rendered fields in token mode, so client metadata such asprovider_specific_fieldsis never named).Usage
fork: <kind>badge; hover for the fields that changed and the sibling it was compared with./graph: each node hasfork: {sibling_node_id, kind, detail}ornull.summary: afork causesline, andstats.fork_kindsin--json, so a harness can be gated on the kind of fork it made and not only onforked == 0.On the fixtures: the real Qwen3 records fork only by re-rendering (20 and 2),
tr_forked_unbridgedby stripped reasoning,tr_shared_replyby two different user follow-ups.Test plan
test/forks.test.js(new): each kind on documents built the way skycap's graph commits them, the token-mode rules, the fixtures, andfork_kindsin the stats.test/server.test.js:/graphcarries the fork on the branch node andnullelsewhere.test/render.test.mjs: the tree shows one badge per branch.Validation
node --test(Node 24.19): 124 passed / 4 failed with this change, 115 passed / 4 failed onmain. The 4 failures are intest/app.test.mjs(route assertions about thegroupsfixture) and fail the same way onmain; nothing here touches them.Also checked by eye on
test/fixtures: the badge sits on the row next to the other sign badges.