TimRad1/dsh-plugin-branchpoint

dsh-plugin-branchpoint

Branchpoint for DeepSeek Harness: fork the current chat into a fresh branch with a compact digest.

未分類branchpointchat-handoffdeepseek

Branchpoint

Fork the conversation at a clean point.

Branchpoint is a DeepSeek Harness (DSH) plugin that adds a fork button to the chat header. Click it and Branchpoint lists the sections it can split off — a practice set, a theory topic, a single formula or code fragment, or the whole branch. Pick one and it opens a fresh session with only that section's digest already in the composer.

Long chats degrade. Compaction helps, but it also blurs the thread. Branchpoint gives you a clean branch that still knows where you were.

What it does

  • Adds a fork icon to conversation.session.header.actions, next to the branch title.
  • Loads up to six older pages of session history when the prompt is outside the current window.
  • Auto-detects splittable units in the branch:
  • sections with numbered tasks («Практика 2», «Задания», «Упражнения»);
  • substantive theory sections («Шаг 1. …», «Инструмент: …»);
  • the whole branch as a fallback.
  • Opens a picker: task sections first with their task count, then theory sections, then «Разобрать» — formulas, functions, code fragments and libraries that matter but are not the topic itself. Each row has a one-line preview.
  • Builds a scoped digest for the chosen unit:
  • the topic name from the first real request;
  • only that section's numbered tasks/questions — no other sections, no context block;
  • formulas stay in their original LaTeX ($\log_2 32$), so DSH renders them with KaTeX exactly as in the main branch; the readable form (log₂(32)) is used only for one-line previews in the picker;
  • one short mode line: «Не решай за меня — жди мои ответы».
  • Keeps «Вся ветка» for the old full summary: goal, all topics, all tasks/questions, conclusion, done/open, files and commands.
  • Opens a new session and puts the digest in the draft. It does not send automatically, so you can review it first.
  • Numbers branches per parent: the digest starts with 🌿 Ветка 1 · …, 🌿 Ветка 2 · …, so the left panel never shows two identical branch titles. The root chat is renamed 🌳 … and pinned once, so the main branch stays visible above its branches.
  • Remembers the parent session. A branch gets a ↩ button that opens the main branch with a short note in its composer: «задания выполнены», «вопрос разобран», or the result and changed files for a code branch.

Example digest

🌿 Ветка 1 · the handoff button does nothing — вся ветка
🎯 Goal: the handoff button does nothing

📌 LATEST CONCLUSION:
Fixed the silent no-op: the digest builder now keeps orphan assistant text and
pages older history before summarizing.

✅ DONE (1):
- silent no-op on empty digest → alert + fallback summary

⏳ OPEN (1):
- in progress: verify the button in a fresh session

📂 STATE:
· changed: lib/client.js
· files: lib/client.js, package.json
· run: npm test

(Summary, not a transcript: intermediate steps are omitted. Continue from this.)

Topic branches

Branchpoint splits a structured lesson or project chat by its Markdown sections. A section with at least two numbered items under a task-like heading becomes a task unit; other sections with enough text become theory units. Selecting a unit creates a branch that knows only that part.

Example: the main chat has «Практика 2» after a change-of-base explanation. The picker shows «Практика 2 — 7 заданий». The new branch gets only this:

🌿 Ветка 1 · 📝 Практика 2
🎯 Логарифмы

1) $\log_4 8$
2) $\log_9 27$
3) $\log_{\sqrt2} 8$
4) $\lg 2 + \lg 5$
...

Не решай за меня — жди мои ответы.
Формулы оформляй в LaTeX-разметке, как в основной ветке.

Formulas keep their original LaTeX, so the branch renders them with KaTeX exactly like the main chat. The picker still shows a readable preview (log₄(8)) because its rows are one line of plain text.

«Разобрать»

Some parts of a lesson matter without being the topic itself: a formula, a function, a code fragment, a library. The picker lists them under «Разобрать», after tasks and theory. Each row opens a narrow branch that carries only that item and the request «Разбери это отдельно, не углубляясь в остальную тему.»

🌿 Ветка 2 · ∑ Формула: log_a(b) = (log_c(b)) / (log_c(a))
🎯 Логарифмы

$$
\log_a b = \frac{\log_c b}{\log_c a}
$$

Разбери это отдельно, не углубляясь в остальную тему.
Формулы оформляй в LaTeX-разметке, как в основной ветке.

Branch numbers and the main chat

Branchpoint numbers the branches of one parent: 🌿 Ветка 1 · …, 🌿 Ветка 2 · …. The number and the section name become the session title in the left panel, so two branches no longer look identical.

The root chat of a branch tree is renamed once to 🌳 … and pinned, so it stays above its branches instead of getting lost among them. Only a real root gets the tree mark; a branch of a branch stays an ordinary 🌿 row.

When «Практика 3» appears later, click the fork button again and split that section off. The main branch stays the map; each branch carries only its own tasks. That keeps context small and focused.

After you finish in the branch, click ↩. Branchpoint opens the main branch and puts a short note in its composer, for example:

↩️ «Логарифмы»: задания «Практика 2» выполнены (проверено 7).

Send it if you want the main chat to record that the section is done. For a code branch the note includes the result and the changed files.

«Вся ветка» still produces the full study digest (all topics, all tasks, answers and checks) when you want the whole lesson in one place.

Install

Not on npm yet. Install the prebuilt tarball from the latest GitHub release:

$tgz = "$env:TEMP\branchpoint.tgz"
Invoke-WebRequest "https://github.com/TimRad1/dsh-plugin-branchpoint/releases/latest/download/branchpoint.tgz" -OutFile $tgz
& "$env:LOCALAPPDATA\Programs\DeepSeek Harness\resources\runtime\cli\bin\dsh.cmd" `
  plugin --profile desktop add ("file:" + ($tgz -replace '\\', '/'))

Or open Settings → Plugins in DSH and install the downloaded .tgz archive.

Fully quit and relaunch DSH. The desktop profile applies plugin composition at startup (it has no HMR).

Use

  1. Open an existing chat with at least one exchange.
  2. Click the fork icon in the header.
  3. Pick a task section, a theory section, a «Разобрать» item, or «Вся ветка».
  4. Review the digest in the new session's composer and send it when ready.
  5. When the branch is done, click ↩ in its header. The main branch opens with a note in the composer; edit or send it.

The button is hidden on a blank session: DSH hides the header actions until the session has history.

How it works

  • lib/index.js is a minimal host half (name, empty apply).
  • lib/client.js:
  • inject = ['slots', 'uiWorkspace', 'sessions'];
  • registers in conversation.session.header.actions;
  • reads ctx.sessions.binding(sessionId).eventSource;
  • entriesToTurns and entriesToTools parse messages and tool calls;
  • loadOlderHistory pages older history (max 6 pages, 12 s);
  • collectUnits splits assistant answers into Markdown or bold headings (ignoring headings inside code fences) and detects numbered task blocks; collectConcepts finds formulas, functions, code fragments and imported libraries;
  • buildUnitDigest renders only the chosen section and keeps formulas as original LaTeX; readableMath is used only for one-line picker previews; buildDigest still renders the full branch;
  • the picker is a React portal (react-dom) with Escape/backdrop close;
  • createBranch uses ctx.uiWorkspace.openWorkspace to capture the new session id and prepareDraft to fill its composer;
  • nextBranchNumber numbers branches per parent; markMain renames the root chat to 🌳 … once and pins it;
  • the parent id and unit metadata are stored in localStorage; returnToMain opens the parent and prepares buildReturnNote as a draft.

No build step: lib/client.js is a ready ESM bundle in the window.__ModuleLoader__ envelope.

Limitations

  • The digest is built from the DSH session event log. Reasoning and raw tool output are not summarized; only visible assistant text, tool errors, changed files and commands are used.
  • The digest framing is English. Quoted conclusions stay in the language of the chat, since they are extracted verbatim.
  • Section detection relies on Markdown headings (## …), bold headings (**…**), and numbered lists (1. …). A plain-prose chat may show no section rows; «Вся ветка» still works.
  • A task section needs at least two numbered items; a theory section needs at least 160 characters.
  • Formulas stay as LaTeX in the digest, so the branch renders them like the main chat after the message is sent. The composer itself is plain text: until you send, $\log_2 32$ is visible as source.
  • Branch numbers count only branches created by 0.6.0 or later for that parent; older branches keep their titles and do not consume a number.
  • The ↩ button appears only for branches created by 0.5.0 or later, and only while the browser keeps the localStorage link.
  • The tree mark and pin are applied once to the root chat when you first split a branch from it. If the chat is unnamed (no visible title yet), the mark is retried on the next branch.
  • The return note replaces any unsent draft in the main composer.
  • History is paged at most six times per click, so extremely long sessions may still need a second click to reach the original prompt.
  • If a branch has no assistant text and no tool results, Branchpoint shows an alert and does not open an empty session.

Development

npm test
node --check lib/client.js
npm pack

To load local changes, install the new .tgz (or link:) and restart DSH.

Changelog

  • 0.6.0 — formulas are no longer rewritten: digests carry the original LaTeX so KaTeX renders them like the main chat; readableMath now only feeds one-line picker previews and no longer leaves begin{cases} / overline{AB} fragments. Adds the «Разобрать» section (formulas, functions, code fragments, libraries) with its own scoped digest. Branches are numbered per parent (🌿 Ветка 1 · …), and the root chat is marked 🌳 and pinned once so it stays above its branches. Adds collectConcepts, nextBranchNumber, markMain, and tests.
  • 0.5.0 — task branches are now minimal: topic, section heading and tasks only, with formulas converted to readable notation. Adds the ↩ return-to-main action with an automatic note («задания выполнены», «вопрос разобран», or result and changed files). Adds readableMath, buildReturnNote, parent-session linking, and tests.
  • 0.4.0 — section picker: auto-detects task and theory units, opens a branch with the chosen section and its nearest formula/rule, keeps «Вся ветка» as fallback. Adds collectUnits, buildUnitDigest, topicOf, and tests for scoped branches.
  • 0.3.1 — study branches keep the original goal, topics, numbered tasks and «why?» questions from the whole branch; answers and checks stay in COVERED; code branches keep all human questions; history paging raised to 6 pages / 12 s; fixed Cyrillic word-boundary detection for answer submissions.
  • 0.3.0 — rebrand as Branchpoint, English digest framing, install from a GitHub release.
  • 0.2.4 — initial public layout.

License

MIT © 2026 TimRad1