<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Xia Chen</title>
    <description>The latest articles on DEV Community by Xia Chen (@chenxiachan).</description>
    <link>https://dev.to/chenxiachan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4048034%2F7b28c2c3-94d8-4d6e-aa74-e10bc1081d78.jpg</url>
      <title>DEV Community: Xia Chen</title>
      <link>https://dev.to/chenxiachan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chenxiachan"/>
    <language>en</language>
    <item>
      <title>Context compaction happens in the dark. I made it happen on a map.</title>
      <dc:creator>Xia Chen</dc:creator>
      <pubDate>Sun, 02 Aug 2026 02:00:37 +0000</pubDate>
      <link>https://dev.to/chenxiachan/context-compaction-happens-in-the-dark-i-made-it-happen-on-a-map-41k2</link>
      <guid>https://dev.to/chenxiachan/context-compaction-happens-in-the-dark-i-made-it-happen-on-a-map-41k2</guid>
      <description>&lt;p&gt;Every long AI session ends the same way. The context window fills up, and something has to give.&lt;/p&gt;

&lt;p&gt;Most tools handle this moment for you. A summarizer wakes up, rewrites your history into a paragraph you never see, and the conversation carries on as if nothing happened. Coding agents call it auto-compact. Agent frameworks call it a condenser. The names differ; the shape is the same: &lt;strong&gt;the most consequential edit of your session is made by a machine, in the dark, and you were not in the room.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What did it keep? What did it drop? Was the decision you spent twenty minutes reaching preserved, or was it flattened into "the user explored several options"? You cannot answer any of these questions, because there is nothing to look at.&lt;/p&gt;

&lt;p&gt;I have been building &lt;a href="https://github.com/chenxiachan/thoughtdag" rel="noopener noreferrer"&gt;ThoughtDAG&lt;/a&gt; around one rule that makes this unacceptable: &lt;strong&gt;a wire is context&lt;/strong&gt;. Your conversation lives as a graph on an infinite canvas. Every answer is a node; the wires between nodes decide exactly what the model sees on the next question. Delete one edge, get a different answer. &lt;a href="https://dev.to/chenxiachan/i-made-llm-context-editable-a-graph-where-the-wires-are-the-prompt-2afl"&gt;I wrote about that rule here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The 30-second visual introduction is embedded above.&lt;/p&gt;

&lt;p&gt;This post is about what that rule forces you to do when the map itself grows too heavy. Compaction has to happen somewhere. The question is whether it happens where you can see it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Condensing, where you can watch
&lt;/h2&gt;

&lt;p&gt;In ThoughtDAG, condensing is not something that happens &lt;em&gt;to&lt;/em&gt; your conversation. It is something you watch happen &lt;em&gt;beside&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fchenxiachan%2Fthoughtdag%2Fmain%2Fdocs%2Fillus%2Fcondense-en.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fchenxiachan%2Fthoughtdag%2Fmain%2Fdocs%2Fillus%2Fcondense-en.svg" alt="Diagram: ThoughtDAG condenses selected linear runs into a side-by-side distilled copy while leaving the original graph untouched" width="440" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Press condense, and the app scans the graph for what I call &lt;strong&gt;runs&lt;/strong&gt;: straight corridors of Q&amp;amp;A where the conversation just marched forward. Three or more turns, one way in, one way out, nothing decisive in the middle. These are the acres of "okay, now try it this way" that every real working session accumulates. The scan is a pure graph walk. No model gets to vote on what counts as collapsible; the structure decides.&lt;/p&gt;

&lt;p&gt;Each candidate run shows up in a list, checked by default, with the token saving printed next to it. Click a run and the canvas flies there, so you can look at what you are about to fold before you fold it. Uncheck anything you want to keep whole.&lt;/p&gt;

&lt;p&gt;Then the build starts, and this is the part I care most about: &lt;strong&gt;your original tree is never touched.&lt;/strong&gt; Condensing builds a second tree beside the first one. Checked runs collapse into distill nodes; every other node is copied as it stands; every wire is rebuilt. The two trees sit on the same canvas, side by side. Nothing was edited. Something new was made.&lt;/p&gt;

&lt;h2&gt;
  
  
  What never gets compressed
&lt;/h2&gt;

&lt;p&gt;The distiller works under fidelity rules that are enforced by structure, not by prompt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Decisions and pivots never collapse.&lt;/strong&gt; Any turn you marked as a ruling-out, a decision, or a change of direction is a landmark. Landmarks survive as full nodes in the condensed tree, always.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your highlights survive verbatim.&lt;/strong&gt; Machine prose gets summarized. Text a human marked as important is carried through word for word. The principle in one line: what the machine said can be compressed; what the human marked must survive as written.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The working frontier is off limits.&lt;/strong&gt; The last three steps above every leaf are where you are thinking right now. The scanner never proposes them, no matter what a model might consider "old".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every distill node knows where it came from.&lt;/strong&gt; A provenance chip on each distilled node jumps back to the exact run it replaced, in the original tree. The audit trail is one click, not an act of faith.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The part where it becomes an experiment
&lt;/h2&gt;

&lt;p&gt;Here is what a visible copy buys you that no black box can offer: &lt;strong&gt;you can test the compression.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Wire the same question into both trees. Ask it twice. One answer runs on the full history; the other runs on the distilled version. If they agree, your condensed tree just proved it carries what matters, and you can archive the original with actual evidence instead of hope. If they diverge, the diff is pointing at exactly what the summary lost, and the chip takes you to the run that needs a closer look.&lt;/p&gt;

&lt;p&gt;Compaction stops being an act of trust in a summarizer. It becomes a comparison you can run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "editable, not autonomous" is the whole point
&lt;/h2&gt;

&lt;p&gt;A reader of the first post left a comment I keep coming back to: keeping the edit rights in human hands is not a feature limitation, it is a trust mechanism. I would push it one step further. Because you hold the edit rights, you can run controlled comparisons. Because you can run comparisons, trust in the tool is earned by evidence, not assumed by default. Visible leads to editable, editable leads to testable. That chain is the product.&lt;/p&gt;

&lt;p&gt;Context compaction was the hardest place to keep that chain intact, because every incentive says: just summarize quietly, nobody looks anyway. Building it as a side-by-side copy, with landmarks pinned and provenance wired in, was the version I could defend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The demo runs in the browser: &lt;strong&gt;no install, no signup&lt;/strong&gt;. Load the example canvas, or drop in a PDF and start from reading. Condense lives in the toolbar once your graph has grown some corridors.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Live demo: &lt;a href="https://app.thoughtdag.workers.dev" rel="noopener noreferrer"&gt;https://app.thoughtdag.workers.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Source: &lt;a href="https://github.com/chenxiachan/thoughtdag" rel="noopener noreferrer"&gt;https://github.com/chenxiachan/thoughtdag&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The one-rule intro, in 30 seconds: &lt;a href="https://www.youtube.com/watch?v=YdJJflUxBi0" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=YdJJflUxBi0&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Delete one edge. Get a different answer. And when the map gets heavy, fold it where everyone can see the folds.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I made LLM context editable: a graph where the wires are the prompt</title>
      <dc:creator>Xia Chen</dc:creator>
      <pubDate>Sun, 26 Jul 2026 14:26:56 +0000</pubDate>
      <link>https://dev.to/chenxiachan/i-made-llm-context-editable-a-graph-where-the-wires-are-the-prompt-2afl</link>
      <guid>https://dev.to/chenxiachan/i-made-llm-context-editable-a-graph-where-the-wires-are-the-prompt-2afl</guid>
      <description>&lt;p&gt;Most LLM interfaces present a conversation as a transcript.&lt;/p&gt;

&lt;p&gt;That works until the conversation branches.&lt;/p&gt;

&lt;p&gt;One branch contains useful research. Another is a discarded hypothesis. A third is an unrelated detour. The interface may show where they came from, but the user often cannot see exactly which branches will be included in the model's next request.&lt;/p&gt;

&lt;p&gt;I wanted to make that state editable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wires are the context
&lt;/h2&gt;

&lt;p&gt;I built an open-source prototype called ThoughtDAG.&lt;/p&gt;

&lt;p&gt;Every question-and-answer exchange is a node on an infinite canvas. An edge is not merely a visual relationship: it determines which upstream nodes are included when the next request is constructed.&lt;/p&gt;

&lt;p&gt;When a user asks from a node, ThoughtDAG walks its incoming graph, orders the relevant ancestors, and turns them into the message sequence sent to the selected model.&lt;/p&gt;

&lt;p&gt;Delete an edge and regenerate the same prompt, and the deleted branch is no longer part of the model's context.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feb5wjxldkfsdthvqvdku.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feb5wjxldkfsdthvqvdku.gif" alt="Deleting an off-topic edge removes that branch from the model's context" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjyhu4o9dsoafh3vfnp5w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjyhu4o9dsoafh3vfnp5w.gif" alt=" " width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a DAG?
&lt;/h2&gt;

&lt;p&gt;I did not want an autonomous system that silently reorganized the user's ideas.&lt;/p&gt;

&lt;p&gt;The graph is directed because context flows from earlier reasoning into later reasoning. It is acyclic because a node should not recursively include itself in its own history.&lt;/p&gt;

&lt;p&gt;This makes three operations explicit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;branching: explore an alternative without modifying the original path;&lt;/li&gt;
&lt;li&gt;merging: synthesize several selected branches;&lt;/li&gt;
&lt;li&gt;pruning: remove irrelevant context before regenerating an answer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The graph is therefore not an agent workflow. It is a visible, human-controlled representation of model memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local-first by default
&lt;/h2&gt;

&lt;p&gt;The canvas is stored in IndexedDB in the browser. There is no account or hosted database.&lt;/p&gt;

&lt;p&gt;ThoughtDAG can connect to Ollama for local inference, or to an arbitrary OpenAI-compatible endpoint. PDFs remain on the user's machine; only extracted text is sent when a remote model is deliberately used.&lt;/p&gt;

&lt;p&gt;The project is MIT licensed and built with React, TypeScript, React Flow, Zustand, Express, and the Vercel AI SDK.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/chenxiachan/thoughtdag" rel="noopener noreferrer"&gt;https://github.com/chenxiachan/thoughtdag&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The question I am testing now is whether people actually want to control context manually, or whether they would rather delegate memory selection to retrieval and agents.&lt;/p&gt;

&lt;p&gt;I would be interested in critiques of that interaction model, especially from people building long-running LLM interfaces.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>showdev</category>
      <category>opensource</category>
      <category>llm</category>
    </item>
  </channel>
</rss>
