<?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>Before Your Coding Agent Edits a File, Let It Ask Why</title>
      <dc:creator>Xia Chen</dc:creator>
      <pubDate>Fri, 04 Sep 2026 15:50:06 +0000</pubDate>
      <link>https://dev.to/chenxiachan/before-your-coding-agent-edits-a-file-let-it-ask-why-4kal</link>
      <guid>https://dev.to/chenxiachan/before-your-coding-agent-edits-a-file-let-it-ask-why-4kal</guid>
      <description>&lt;p&gt;AI coding agents can modify an unfamiliar file in seconds. The slower question is often more important:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does this code look this way?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer may be scattered across old local sessions: one turn investigated the bug, another rejected an approach, and a later turn made the edit. Git preserves the code change, but not necessarily the surrounding agent conversation.&lt;/p&gt;

&lt;p&gt;I added a local query layer to &lt;a href="https://github.com/chenxiachan/thoughtdag" rel="noopener noreferrer"&gt;ThoughtDAG&lt;/a&gt; so a developer—or a coding agent—can deliberately retrieve that history before editing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx thoughtdag why src/lib/api.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It searches supported local agent transcripts for turns that changed, read, or discussed the file and returns links to the matching source turns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observation is not explanation
&lt;/h2&gt;

&lt;p&gt;The difficult part was not text search. It was avoiding a false claim of causality.&lt;/p&gt;

&lt;p&gt;If a session record shows a file edit, ThoughtDAG can report that as an observed change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Δ storedProviders → storedProviders, storedVision…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the agent later says why it made the change, that is useful—but it is still the agent's account, not a verified causal fact. ThoughtDAG marks that separately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;≈ candidate explanation from the agent response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This distinction matters when old session history becomes input to another agent. A fluent explanation should not silently harden into ground truth just because it was retrieved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrieval stays deliberate
&lt;/h2&gt;

&lt;p&gt;For regular use, the same index can be exposed through read-only MCP tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; thoughtdag
thoughtdag setup mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent can then call &lt;code&gt;why_check&lt;/code&gt;, &lt;code&gt;why_file&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt;, and &lt;code&gt;recall_turn&lt;/code&gt; before changing code. Retrieval is explicit; matching history is not automatically injected into every prompt.&lt;/p&gt;

&lt;p&gt;The index stays on the local machine, and source session files are never modified. The current CLI covers local Claude Code, Codex, and ThoughtDAG canvas conversations.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does not prove
&lt;/h2&gt;

&lt;p&gt;This is a developer preview, not a complete audit trail.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An observed edit proves that the recorded session changed a file, not that every reason for the change was captured.&lt;/li&gt;
&lt;li&gt;A matching turn can be relevant without being sufficient.&lt;/li&gt;
&lt;li&gt;External session formats can drift.&lt;/li&gt;
&lt;li&gt;Missing or unrecorded actions remain missing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those limits are why the output keeps provenance visible and separates observations from candidate explanations.&lt;/p&gt;

&lt;p&gt;I am now testing a stricter workflow: before editing an old file, an agent first checks whether there is relevant local history, opens the exact turn when needed, and only then decides what belongs in its current context.&lt;/p&gt;

&lt;p&gt;What would you want such a pre-edit check to surface: rejected alternatives, linked issues, tests that once failed, or something else?&lt;/p&gt;

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

&lt;p&gt;Disclosure: I maintain ThoughtDAG. This article was drafted with AI assistance and manually checked against the released CLI and documentation.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>programming</category>
    </item>
    <item>
      <title>Your Local Agent Session Should Be a Source, Not Hidden Memory</title>
      <dc:creator>Xia Chen</dc:creator>
      <pubDate>Wed, 02 Sep 2026 16:52:04 +0000</pubDate>
      <link>https://dev.to/chenxiachan/your-local-agent-session-should-be-a-source-not-hidden-memory-l0m</link>
      <guid>https://dev.to/chenxiachan/your-local-agent-session-should-be-a-source-not-hidden-memory-l0m</guid>
      <description>&lt;p&gt;My useful agent work rarely lives in one conversation.&lt;/p&gt;

&lt;p&gt;One session investigates a bug. Another compares designs. A third edits the code. The important context is spread across terminal logs, tool calls, files, and compacted summaries.&lt;/p&gt;

&lt;p&gt;The usual answer is “give the agent better memory.” I wanted a stricter boundary instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source session  -&amp;gt;  editable mirror  -&amp;gt;  compiled model context
  read-only           user-owned             explicit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That boundary became &lt;strong&gt;Session Atlas&lt;/strong&gt;, a new desktop feature in &lt;a href="https://github.com/chenxiachan/thoughtdag" rel="noopener noreferrer"&gt;ThoughtDAG&lt;/a&gt;. It currently reads supported local Codex and Claude Code sessions, groups them by project, and opens them as graph mirrors.&lt;/p&gt;

&lt;p&gt;The point is not to turn a transcript into a prettier transcript. It is to separate three things that are often conflated:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;what the agent actually recorded;&lt;/li&gt;
&lt;li&gt;what the user wants to keep, reorganize, or connect;&lt;/li&gt;
&lt;li&gt;what the next model request should receive.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The source stays read-only
&lt;/h2&gt;

&lt;p&gt;Atlas never rewrites the original session file. The source remains the record of what the external agent did.&lt;/p&gt;

&lt;p&gt;The imported graph is an independent mirror. I can edit a mirrored node, remove a wire, add a PDF or note, or create a new branch without mutating the source history. Questions asked inside ThoughtDAG belong to the canvas; they are not written back into the source agent session.&lt;/p&gt;

&lt;p&gt;This distinction matters because “editing history” and “curating future context” are different operations. The first changes the record. The second changes what happens next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5hi5itd05g638xobgymx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5hi5itd05g638xobgymx.gif" alt="Two local agent turns imported as graph nodes, with tool activity attached to the turn that produced it" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each user-and-agent turn becomes one conversation node. Tool calls and results are paired as attachments on that node rather than flattened into fake conversational turns. The mirror also keeps the runner, session ID, source turn identifiers, working directory, and truncation markers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visible is not the same as included
&lt;/h2&gt;

&lt;p&gt;An imported turn can remain visible on the canvas without entering the next request.&lt;/p&gt;

&lt;p&gt;In ThoughtDAG, wires are part of the context definition. Incoming paths and explicit references determine which nodes and attachments are compiled for the model. Removing a wire excludes that branch from downstream model context while leaving it available for inspection or reconnection.&lt;/p&gt;

&lt;p&gt;That gives the graph two jobs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a durable human workspace for the project;&lt;/li&gt;
&lt;li&gt;an executable description of model context.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is intentionally different from automatic retrieval. Atlas does not claim that every visible artifact is relevant, and it does not silently choose a hidden memory set on the user's behalf.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mirror keeps listening
&lt;/h2&gt;

&lt;p&gt;A mirror is not just a one-time import. If the source agent keeps working, Atlas watches the supported local session store and appends new turns incrementally.&lt;/p&gt;

&lt;p&gt;The append path uses a per-session ledger:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source file changes
        -&amp;gt; identify the session
        -&amp;gt; skip turns before the ledger boundary
        -&amp;gt; append only unseen turns to that session's tail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Existing nodes are not moved. Edited mirror text is not overwritten. A session registered to another canvas does not silently append to the current one. Deleting every mirrored node for a session removes its subscription, so intentionally deleted work does not grow back.&lt;/p&gt;

&lt;p&gt;The harder problem here was not parsing JSONL. It was deciding which invariants should survive updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  One project can contain several agents
&lt;/h2&gt;

&lt;p&gt;Atlas groups sessions by their recorded working directory. That lets work from supported runners meet at the project level without pretending they share one native history.&lt;/p&gt;

&lt;p&gt;I can place several sessions on one canvas and decide whether they connect. I can also take the curated upstream context from a node into a fresh CLI session, continue the work there, and mount the returned session back at the departure point.&lt;/p&gt;

&lt;p&gt;This is still human-controlled context transfer, not autonomous orchestration. Atlas does not schedule agents, grant permissions, or allocate resources. Creating the next session and choosing its context remain explicit actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just rely on compaction?
&lt;/h2&gt;

&lt;p&gt;Compaction is useful, but a summary is a lossy state transition. After compaction, it can be difficult to inspect which tool result, abandoned hypothesis, or source passage led to a decision.&lt;/p&gt;

&lt;p&gt;Atlas sits above that mechanism. It preserves the source session while letting the user curate a finer-grained project context across turns and agents.&lt;/p&gt;

&lt;p&gt;The architecture is deliberately conservative:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the source is evidence;&lt;/li&gt;
&lt;li&gt;the mirror is editable;&lt;/li&gt;
&lt;li&gt;model context is compiled from explicit graph structure;&lt;/li&gt;
&lt;li&gt;cross-agent handoff is visible and user-triggered.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Current limits
&lt;/h2&gt;

&lt;p&gt;Session Atlas is a desktop/local feature. It currently supports native scanning of local Codex and Claude Code sessions, and runner formats can change. The web demo does not have arbitrary filesystem access, so it cannot provide local session discovery.&lt;/p&gt;

&lt;p&gt;This is also not an “Agent OS.” It is a visual coordination and context-transfer layer. I would rather keep that boundary honest than imply autonomy the product does not have.&lt;/p&gt;

&lt;p&gt;The feature is available in &lt;a href="https://github.com/chenxiachan/thoughtdag/releases/tag/v0.4.2" rel="noopener noreferrer"&gt;ThoughtDAG v0.4.2&lt;/a&gt;. The &lt;a href="https://chenxiachan.github.io/thoughtdag/docs/guides/session-atlas" rel="noopener noreferrer"&gt;Session Atlas guide&lt;/a&gt; documents the import, live append, source configuration, and CLI handoff paths. There is also a &lt;a href="https://www.youtube.com/watch?v=Rs_KPYj2NCU" rel="noopener noreferrer"&gt;45-second walkthrough&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am especially interested in two kinds of feedback:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Which other local agent session format should be supported next?&lt;/li&gt;
&lt;li&gt;Where should the boundary sit between automatic context suggestions and explicit user control?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Disclosure: I maintain ThoughtDAG. This article was drafted with AI assistance and manually checked against the released v0.4.2 implementation and documentation.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>programming</category>
      <category>news</category>
    </item>
    <item>
      <title>I Deleted the Wrong Turn. Three LLM Endpoints Still Repeated Its Answer.</title>
      <dc:creator>Xia Chen</dc:creator>
      <pubDate>Mon, 24 Aug 2026 01:21:04 +0000</pubDate>
      <link>https://dev.to/chenxiachan/i-deleted-the-wrong-turn-three-llm-endpoints-still-repeated-its-answer-3fb5</link>
      <guid>https://dev.to/chenxiachan/i-deleted-the-wrong-turn-three-llm-endpoints-still-repeated-its-answer-3fb5</guid>
      <description>&lt;p&gt;I assumed that removing a wrong turn would repair an LLM conversation.&lt;/p&gt;

&lt;p&gt;Then I tested it.&lt;/p&gt;

&lt;p&gt;In one deliberately simple case, a conversation began with a verified value of 24 parts per crate. A later turn falsely changed it back to 30. Several downstream answers then calculated from that mistake and recorded 131 as the total.&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%2F893o3gis67lroemwsyol.png" 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%2F893o3gis67lroemwsyol.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I deleted the false turn and asked the same final question again.&lt;/p&gt;

&lt;p&gt;Three of nine model endpoints still answered &lt;strong&gt;131&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The false source was gone. Its consequences were still in the context.&lt;/p&gt;

&lt;p&gt;That result led me to build the &lt;a href="https://huggingface.co/datasets/thoughtdag/context-repair-benchmark" rel="noopener noreferrer"&gt;ThoughtDAG Context Repair Benchmark&lt;/a&gt;, a public dataset containing 27 graph cases and 1,485 captured model conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  One wrong turn, five context graphs
&lt;/h2&gt;

&lt;p&gt;The flagship case uses arithmetic so every answer can be scored exactly, without an LLM judge.&lt;/p&gt;

&lt;p&gt;The fixed inputs are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4 crates&lt;/li&gt;
&lt;li&gt;24 verified parts per crate&lt;/li&gt;
&lt;li&gt;11 loose parts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The correct answer is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4 × 24 + 11 = 107
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The polluted branch tells the model to ignore the verified recount and return to 30. Its descendants then calculate &lt;code&gt;120&lt;/code&gt;, add the loose parts, and preserve &lt;code&gt;131&lt;/code&gt; as the current working total.&lt;/p&gt;

&lt;p&gt;I asked the same final question under five graph conditions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clean context&lt;/li&gt;
&lt;li&gt;Polluted context&lt;/li&gt;
&lt;li&gt;Delete the false source only&lt;/li&gt;
&lt;li&gt;Delete the contaminated subgraph&lt;/li&gt;
&lt;li&gt;Delete the source and recompute its descendants&lt;/li&gt;
&lt;/ol&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%2F4th718ty60si7vli4hle.png" 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%2F4th718ty60si7vli4hle.png" alt="Five graph states in the flagship context-repair case" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All nine endpoints returned 107 with clean context and 131 with polluted context. After source-only deletion, six recovered to 107 while three still returned 131. Removing the contaminated subgraph or recomputing its descendants restored 107 across all nine endpoints on this case.&lt;/p&gt;

&lt;p&gt;The surviving error was not hidden memory. Later conversation turns still contained values derived from the deleted source. Once generated text becomes part of the next request, it can carry an error independently of the turn that created it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Removing evidence and repairing consequences are different operations
&lt;/h2&gt;

&lt;p&gt;A linear transcript makes an error look local. One message is wrong, so we edit or delete that message.&lt;/p&gt;

&lt;p&gt;A long conversation contains dependencies. One answer may calculate from a bad claim. Another may summarize that calculation. A third may treat the summary as established state.&lt;/p&gt;

&lt;p&gt;By then, context repair has two parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Remove the bad evidence.&lt;/li&gt;
&lt;li&gt;Repair or remove the downstream text derived from it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A graph makes those descendants visible. It also gives us explicit interventions to compare.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pilot
&lt;/h2&gt;

&lt;p&gt;The public pilot contains nine independent task families at propagation depths one, two, and three. Each case is evaluated under the same five graph conditions. Nine model endpoints produced 1,215 main results. A controlled reasoning comparison added another 270.&lt;/p&gt;

&lt;p&gt;Headline repair rates include only model-cases that were correct under clean context and became wrong after pollution. This happened 18 times per endpoint, giving 162 paired model-case outcomes across the panel.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Repair operation&lt;/th&gt;
&lt;th&gt;Repaired&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Delete the false source only&lt;/td&gt;
&lt;td&gt;152 / 162&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete the source and recompute descendants&lt;/td&gt;
&lt;td&gt;161 / 162&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete the contaminated subgraph&lt;/td&gt;
&lt;td&gt;162 / 162&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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%2Ftvkvx7fwt7xjvgjb1hl6.png" 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%2Ftvkvx7fwt7xjvgjb1hl6.png" alt="Recovery rates for three context-repair strategies" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source-only deletion worked most of the time, but ten outcomes still carried the error. Nine of those failures involved false supersession, where a once-correct value had been incorrectly rolled back. After the rollback itself disappeared, its echoes looked like ordinary conversation history.&lt;/p&gt;

&lt;p&gt;Subgraph pruning was the most reliable operation in this pilot because it removed the false source and every frozen statement derived from it. Recomputing preserved more of the reasoning path, but each regenerated step introduced another opportunity for error. One recomputation failed for that reason.&lt;/p&gt;

&lt;p&gt;This suggests a practical rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use source pruning when later turns do not depend on the mistake.&lt;/li&gt;
&lt;li&gt;Recompute descendants when the path is valuable and the regenerated outputs can be checked.&lt;/li&gt;
&lt;li&gt;Remove the affected subgraph when reliable excision matters most.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reasoning helped repair the context, not resist the pollution
&lt;/h2&gt;

&lt;p&gt;I also ran one controlled comparison on a text-only endpoint with reasoning explicitly enabled and disabled per request.&lt;/p&gt;

&lt;p&gt;The model was derailed by pollution in the same 18 cases under both settings. The difference appeared after source-only pruning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reasoning enabled: &lt;strong&gt;16 / 18 repaired&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;reasoning disabled: &lt;strong&gt;2 / 18 repaired&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recomputation repaired 18 / 18 under both settings.&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%2Fz26pjreh6f4o2lfthrbw.png" 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%2Fz26pjreh6f4o2lfthrbw.png" alt="Controlled reasoning ablation" width="800" height="696"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is one endpoint and one provider control. It does not establish a general result about reasoning models. It does show why context sensitivity and context repair should be measured separately. In this run, reasoning did not stop the model from accepting conflicting context. It helped the model reconcile what remained after a partial repair.&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%2F67x9n7me7c3omxia0xah.png" 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%2F67x9n7me7c3omxia0xah.png" alt=" " width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The dataset is public
&lt;/h2&gt;

&lt;p&gt;I published the cases and results as a Hugging Face Dataset:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/datasets/thoughtdag/context-repair-benchmark" rel="noopener noreferrer"&gt;Browse the dataset and results&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chenxiachan.github.io/thoughtdag/research/context-repair-pilot-v2/" rel="noopener noreferrer"&gt;Read the interactive report&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/chenxiachan/thoughtdag/tree/main/benchmark" rel="noopener noreferrer"&gt;Inspect the benchmark pipeline&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Dataset Viewer exposes three configurations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cases&lt;/code&gt;: graph structures, interventions, gold answers, and scorers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;endpoint_results&lt;/code&gt;: 1,215 rows from the nine-endpoint panel&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;reasoning_ablation&lt;/code&gt;: 270 rows from the controlled comparison&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The executable pipeline and immutable traces remain in the GitHub repository. The Hugging Face dataset is the research distribution layer, so the evidence can be browsed and loaded without cloning the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;p&gt;These are pilot and reference results. The tasks are synthetic, symbolic, English-only, and scored by exact numeric match. Depth variants from one family are repeated measures. The endpoint panel is a convenience sample, and several free endpoints may drift over time.&lt;/p&gt;

&lt;p&gt;The benchmark does not explain why a model generated a token. It tests a narrower question: when we change the context graph, does the answer change in the expected direction?&lt;/p&gt;

&lt;p&gt;That is the role of ThoughtDAG here. Its wires determine which upstream nodes enter the next request. Graph editing becomes an experimental intervention instead of a visual metaphor.&lt;/p&gt;

&lt;p&gt;The first two posts in this series focused on making context &lt;a href="https://dev.to/chenxiachan/i-made-llm-context-editable-a-graph-where-the-wires-are-the-prompt-2afl"&gt;visible&lt;/a&gt; and &lt;a href="https://dev.to/chenxiachan/context-compaction-happens-in-the-dark-i-made-it-happen-on-a-map-41k2"&gt;editable&lt;/a&gt;. This benchmark is the third step: making context changes testable.&lt;/p&gt;

&lt;p&gt;If you work on long-running LLM conversations, I would especially value critiques of the case design and suggestions for the next control condition.&lt;/p&gt;

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

</description>
      <category>ai</category>
      <category>llm</category>
      <category>testing</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I Removed One Edge from an LLM Context. The Answer Changed.</title>
      <dc:creator>Xia Chen</dc:creator>
      <pubDate>Thu, 20 Aug 2026 13:47:04 +0000</pubDate>
      <link>https://dev.to/chenxiachan/i-removed-one-edge-from-an-llm-context-the-answer-changed-1j9o</link>
      <guid>https://dev.to/chenxiachan/i-removed-one-edge-from-an-llm-context-the-answer-changed-1j9o</guid>
      <description>&lt;p&gt;Most LLM interfaces let you edit the latest prompt. Far fewer let you edit the history that prompt will inherit.&lt;/p&gt;

&lt;p&gt;I wanted to test a simple failure mode: &lt;strong&gt;what happens when one incorrect research note remains inside a long-running conversation?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/PF_uhanaoQg"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  A small context intervention
&lt;/h2&gt;

&lt;p&gt;I built a controlled scenario in ThoughtDAG.&lt;/p&gt;

&lt;p&gt;A source node reported &lt;strong&gt;17% worse&lt;/strong&gt; performance. A deliberately corrupted note reversed that result and said &lt;strong&gt;17% better&lt;/strong&gt;. That note then flowed into a later recommendation.&lt;/p&gt;

&lt;p&gt;With the incorrect branch still connected, the model repeated the wrong conclusion.&lt;/p&gt;

&lt;p&gt;I then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;kept the model unchanged;&lt;/li&gt;
&lt;li&gt;kept the final question unchanged;&lt;/li&gt;
&lt;li&gt;removed the single edge carrying the contaminated branch;&lt;/li&gt;
&lt;li&gt;regenerated the answer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The recommendation changed.&lt;/p&gt;

&lt;p&gt;Within this run, the only deliberate intervention was the context selected by the graph.&lt;/p&gt;

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

&lt;p&gt;ThoughtDAG represents conversation turns, document excerpts, and extracted material as nodes on a canvas.&lt;/p&gt;

&lt;p&gt;The edges are not decorative. When a user asks from a node, ThoughtDAG walks its upstream graph and serializes only those connected ancestors into the next model request.&lt;/p&gt;

&lt;p&gt;That makes three operations concrete:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;branch&lt;/strong&gt; to investigate an alternative without rewriting the original path;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;merge&lt;/strong&gt; selected lines of inquiry;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;prune&lt;/strong&gt; a branch so it stays visible on the canvas but leaves the next request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deleting a wire is therefore different from merely hiding a message in the interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does not prove
&lt;/h2&gt;

&lt;p&gt;This is a small controlled demonstration, not yet a general benchmark.&lt;/p&gt;

&lt;p&gt;It does not reveal the model's internal reasoning, attention weights, or the exact causal contribution of every token. It tests something more observable: &lt;strong&gt;which prior material was actually included in the request, and what happened after that input changed?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A rigorous benchmark would need repeated runs, fixed decoding settings where possible, multiple models, several contamination types, and published evaluation criteria.&lt;/p&gt;

&lt;p&gt;That is the direction I want to explore next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try the experiment
&lt;/h2&gt;

&lt;p&gt;ThoughtDAG is local-first, MIT licensed, and supports Ollama and OpenAI-compatible endpoints.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/chenxiachan/thoughtdag" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chenxiachan.github.io/thoughtdag/" rel="noopener noreferrer"&gt;Project website&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am especially interested in one design question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should context cleanup stay visible and human-controlled, or should retrieval and agents decide what the model remembers?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you try the same kind of intervention with another model, I would be interested in the graph, model settings, and before/after answers.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Deleting the Source Is Not Enough: How Context Errors Survive in LLM Conversations</title>
      <dc:creator>Xia Chen</dc:creator>
      <pubDate>Tue, 18 Aug 2026 11:39:50 +0000</pubDate>
      <link>https://dev.to/chenxiachan/deleting-the-source-is-not-enough-how-context-errors-survive-in-llm-conversations-2lp1</link>
      <guid>https://dev.to/chenxiachan/deleting-the-source-is-not-enough-how-context-errors-survive-in-llm-conversations-2lp1</guid>
      <description>&lt;p&gt;Suppose an LLM conversation contains a wrong correction. You remove that turn. Is the conversation repaired?&lt;/p&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;By the time you notice the error, later answers may already have repeated it, calculated from it, and turned it into new claims. Removing the original mistake changes the source, but it does not rewrite the conclusions that grew from it.&lt;/p&gt;

&lt;p&gt;I built a small controlled benchmark to test that distinction. Across 72 paired cases in which conflicting context first caused a wrong answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deleting only the original bad turn repaired &lt;strong&gt;68/72&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;deleting the source and recomputing its descendants repaired &lt;strong&gt;71/72&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;removing the entire contaminated subgraph repaired &lt;strong&gt;72/72&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are pilot results, not an authoritative model leaderboard. The narrower finding is that a conversational error can survive as downstream state after its source has disappeared.&lt;/p&gt;

&lt;h2&gt;
  
  
  One concrete failure
&lt;/h2&gt;

&lt;p&gt;The flagship case is deliberately simple, so the final answer can be scored without an LLM judge.&lt;/p&gt;

&lt;p&gt;The conversation starts with three quantities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4 crates;&lt;/li&gt;
&lt;li&gt;30 parts per crate;&lt;/li&gt;
&lt;li&gt;11 loose parts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A verified recount then corrects the second quantity from 30 to 24. The correct total is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4 × 24 + 11 = 107
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, a false turn tells the model to ignore the recount and return to 30. Three later turns propagate the mistake:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;4 × 30 = 120&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;120 + 11 = 131&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;a restatement records &lt;code&gt;30&lt;/code&gt;, &lt;code&gt;120&lt;/code&gt;, and &lt;code&gt;131&lt;/code&gt; as the current working values&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The final question is always the same: using the fixed inputs, return the total as a single number.&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%2F4th718ty60si7vli4hle.png" 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%2F4th718ty60si7vli4hle.png" alt="Five graph states in the flagship context-repair case" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Four model endpoints were tested at temperature 0 with provider-default reasoning settings.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Graph condition&lt;/th&gt;
&lt;th&gt;GLM 4.5 Flash&lt;/th&gt;
&lt;th&gt;Nemotron 3.5 Lightning&lt;/th&gt;
&lt;th&gt;Gemma 4 26B&lt;/th&gt;
&lt;th&gt;GPT-OSS 20B&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Clean&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Polluted&lt;/td&gt;
&lt;td&gt;131&lt;/td&gt;
&lt;td&gt;131&lt;/td&gt;
&lt;td&gt;131&lt;/td&gt;
&lt;td&gt;131&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete source only&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;131&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;131&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete contaminated subgraph&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete source and recompute&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Gemma and GPT-OSS produced the same wrong answer after the false reversal itself had been removed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;131 = 4 × 30 + 11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The error was no longer present at its source. It survived through the downstream turns that had already absorbed it.&lt;/p&gt;

&lt;p&gt;This is not evidence of hidden memory or inaccessible reasoning. The stale value remained plainly visible in later context. The problem is structural: deleting one turn does not invalidate text that was previously generated from it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why deleting the source did not fully repair the context
&lt;/h2&gt;

&lt;p&gt;In a linear transcript, a correction looks local. A message was wrong, so you edit or delete that message.&lt;/p&gt;

&lt;p&gt;But a multi-turn conversation contains dependencies. A later answer may summarize the bad claim. Another may calculate from that summary. A third may restate the result as the new working state.&lt;/p&gt;

&lt;p&gt;Once that happens, the descendants become independent carriers of the error. Removing the original source changes what &lt;em&gt;should&lt;/em&gt; be believed, but downstream text can continue to say the opposite.&lt;/p&gt;

&lt;p&gt;This suggests that context repair has at least two distinct operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Remove the bad evidence.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Repair or remove the consequences derived from it.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A graph makes this difference explicit. The source has descendants, and those descendants can be pruned or regenerated in dependency order.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experimental design
&lt;/h2&gt;

&lt;p&gt;The pilot contains 9 objectively scored task families, each instantiated at propagation depths 1, 2, and 3. The tasks use simple arithmetic state so the expected answer is deterministic and scoring does not require an LLM judge.&lt;/p&gt;

&lt;p&gt;Each model received the same final question under five graph conditions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Condition&lt;/th&gt;
&lt;th&gt;Context presented to the model&lt;/th&gt;
&lt;th&gt;What it tests&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Clean&lt;/td&gt;
&lt;td&gt;Verified value followed by clean intermediate turns&lt;/td&gt;
&lt;td&gt;Can the model solve the task at all?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Polluted&lt;/td&gt;
&lt;td&gt;False reversal plus contaminated descendants&lt;/td&gt;
&lt;td&gt;Does the error change the answer?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source prune&lt;/td&gt;
&lt;td&gt;False reversal removed, descendants retained&lt;/td&gt;
&lt;td&gt;Is deleting the source sufficient?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Subgraph prune&lt;/td&gt;
&lt;td&gt;False reversal and contaminated descendants removed&lt;/td&gt;
&lt;td&gt;Does complete excision restore the answer?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recompute descendants&lt;/td&gt;
&lt;td&gt;False reversal removed, descendants regenerated in dependency order&lt;/td&gt;
&lt;td&gt;Can the line of inquiry be repaired rather than discarded?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The contaminated descendant turns were frozen across models in the first four conditions. Every model therefore saw the same faulty history. Only the recompute condition asked each model to regenerate those descendants.&lt;/p&gt;

&lt;p&gt;This separates two questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How sensitive is a model to a fixed contaminated context?&lt;/li&gt;
&lt;li&gt;How well can it rebuild the chain after the graph is corrected?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Headline repair metrics are conditioned on cases the model first answered correctly under clean context and then answered incorrectly after pollution. This avoids counting a repair failure when the model could not solve the clean task in the first place.&lt;/p&gt;

&lt;p&gt;Across four endpoints, the pilot captured 540 conditions with no capture failures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four-model results
&lt;/h2&gt;

&lt;p&gt;Context sensitivity was strikingly consistent across the four model endpoints.&lt;/p&gt;

&lt;p&gt;For every model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clean context: &lt;strong&gt;27/27 correct&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;explicit misinformation: &lt;strong&gt;9/9 caused a wrong answer&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;false supersession of a verified update: &lt;strong&gt;9/9 caused a wrong answer&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;a numerically similar but irrelevant aside: &lt;strong&gt;0/9 caused a wrong answer&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this pilot, semantic conflict mattered more than superficial numerical distraction.&lt;/p&gt;

&lt;p&gt;The repair strategies then separated:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Repair operation&lt;/th&gt;
&lt;th&gt;Recovered&lt;/th&gt;
&lt;th&gt;Recovery rate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Delete contaminated subgraph&lt;/td&gt;
&lt;td&gt;72/72&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete source and recompute descendants&lt;/td&gt;
&lt;td&gt;71/72&lt;/td&gt;
&lt;td&gt;98.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete source only&lt;/td&gt;
&lt;td&gt;68/72&lt;/td&gt;
&lt;td&gt;94.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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%2Ftvkvx7fwt7xjvgjb1hl6.png" 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%2Ftvkvx7fwt7xjvgjb1hl6.png" alt="Recovery rates for three context-repair strategies" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All four source-prune failures occurred in false-supersession cases at propagation depth 2 or 3. Gemma showed the clearest depth pattern: source-only repair succeeded in 6/6 derailed cases at depth 1, 5/6 at depth 2, and 4/6 at depth 3.&lt;/p&gt;

&lt;p&gt;The per-model repair counts were:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Source prune&lt;/th&gt;
&lt;th&gt;Subgraph prune&lt;/th&gt;
&lt;th&gt;Recompute descendants&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nemotron 3.5 Lightning&lt;/td&gt;
&lt;td&gt;18/18&lt;/td&gt;
&lt;td&gt;18/18&lt;/td&gt;
&lt;td&gt;18/18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GLM 4.5 Flash&lt;/td&gt;
&lt;td&gt;18/18&lt;/td&gt;
&lt;td&gt;18/18&lt;/td&gt;
&lt;td&gt;17/18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-OSS 20B&lt;/td&gt;
&lt;td&gt;17/18&lt;/td&gt;
&lt;td&gt;18/18&lt;/td&gt;
&lt;td&gt;18/18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemma 4 26B&lt;/td&gt;
&lt;td&gt;15/18&lt;/td&gt;
&lt;td&gt;18/18&lt;/td&gt;
&lt;td&gt;18/18&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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%2Fvwmgqtj5gcuma1wbrq61.png" 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%2Fvwmgqtj5gcuma1wbrq61.png" alt="Repair successes by model and repair strategy" width="799" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The single recomputation failure is important too. Replaying a corrected graph does not guarantee a correct result. A model can introduce a new mistake while rebuilding the chain. Dependency-aware replay makes the operation explicit and reproducible, but it does not replace verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why pruning the subgraph was more stable
&lt;/h2&gt;

&lt;p&gt;Deleting the contaminated subgraph is the most conservative repair. It removes both the bad source and every frozen statement derived from it. The next answer therefore cannot inherit the stale value through those descendants.&lt;/p&gt;

&lt;p&gt;Recomputing descendants preserves more of the line of inquiry. Instead of discarding the branch, it regenerates affected nodes from upstream to downstream using the corrected context. That is useful, but it adds fresh inference steps, and each inference is another opportunity for error.&lt;/p&gt;

&lt;p&gt;Source-only deletion makes the smallest edit, but it leaves the largest burden on the model: the request still contains downstream claims that contradict the now-correct upstream state.&lt;/p&gt;

&lt;p&gt;The pilot therefore suggests a practical hierarchy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Source prune&lt;/strong&gt; when descendants do not repeat or depend on the error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recompute descendants&lt;/strong&gt; when the reasoning path is worth preserving and outputs can be checked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subgraph prune&lt;/strong&gt; when reliable removal matters more than preserving the affected branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What the pilot does and does not establish
&lt;/h2&gt;

&lt;p&gt;The result supports four narrow conclusions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A conversational error can become downstream state.&lt;/li&gt;
&lt;li&gt;Removing evidence and repairing its consequences are different operations.&lt;/li&gt;
&lt;li&gt;Recalculation should follow dependency order.&lt;/li&gt;
&lt;li&gt;Graph editing can serve as an experimental intervention rather than a visual metaphor.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It does &lt;strong&gt;not&lt;/strong&gt; establish a general ranking of the four models. The tasks are synthetic, each endpoint was run once at temperature 0, and provider-default reasoning behavior was not normalized across providers.&lt;/p&gt;

&lt;p&gt;It also does not reveal why a model generated a particular token, measure hidden reasoning, or show that every real conversation benefits from manual graph editing.&lt;/p&gt;

&lt;p&gt;The next iterations need stronger controls, more task families, repeated runs, and a local-model track. The benchmark is designed so new model endpoints can be run against the same graph cases and scored without another model acting as judge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce and inspect
&lt;/h2&gt;

&lt;p&gt;The benchmark stores graph cases, exact serialized requests, responses, usage, declarative scores, and importable ThoughtDAG canvases.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://chenxiachan.github.io/thoughtdag/research/context-repair-pilot-v1/" rel="noopener noreferrer"&gt;Canonical report&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/chenxiachan/thoughtdag/blob/main/benchmark/cases/repair/pilot-depot-crates-k3.case.json" rel="noopener noreferrer"&gt;Flagship case specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/chenxiachan/thoughtdag/blob/main/benchmark/canvases/results/rp-pilot-depot-crates-k3.story.thoughtdag.json" rel="noopener noreferrer"&gt;Importable flagship story canvas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/chenxiachan/thoughtdag/blob/main/benchmark/STATUS.md" rel="noopener noreferrer"&gt;Pilot status and aggregate results&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/chenxiachan/thoughtdag/blob/main/benchmark/DESIGN.md" rel="noopener noreferrer"&gt;Benchmark design&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ThoughtDAG is the open-source reference implementation used to visualize and reproduce these interventions. Its central rule is simple: &lt;strong&gt;wires are the context&lt;/strong&gt;. An edge determines which upstream nodes enter the next model request, so pruning or replaying part of the graph changes the serialized context rather than only the layout.&lt;/p&gt;

&lt;p&gt;The benchmark is not evidence that ThoughtDAG is the only way to perform these interventions. It is a concrete, inspectable interface for testing them.&lt;/p&gt;

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

</description>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
      <category>computerscience</category>
    </item>
    <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>
