Um, from what I found when I tried it:
I think the experiment is getting more interesting once the question is split into a few separate layers.
The short version of my answers to your three questions would be:
| Question |
My current take |
| What should be logged? |
The graph operation is only part of it. I would log the exact request payload your harness sent, model/runtime identity, generation termination, raw output, and evaluator state. In particular, finish_reason / output-cap hits turned out to matter in a small check I ran. |
| When is manual pruning useful vs automatic memory/RAG? |
I would not make this a binary contest. Manual control seems especially useful for debugging, auditing, research interventions, and exceptional cases; automatic selection is better suited to routine scale; a hybrid where the system proposes and the human can inspect/override seems like a very natural third condition for ThoughtDAG. |
| Worth testing across models/context sizes? |
Yes, but I would separate semantic content, position, actual input length, and model/backend rather than just increasing the nominal context window or adding more models at once. |
The framing that now makes the most sense to me is:
detecting that a branch is bad and repairing the context after that branch is already known to be bad are different experiments.
Your current graph intervention is particularly clean as the second kind.
That distinction lets the current experiment stay narrow without asking it to solve the harder adjudication problem at the same time.
1. For reproducibility, I would log four layers
Something roughly like this:
intervention identity
↓
model/runtime identity
↓
execution outcome
↓
evaluation identity
Intervention
- graph snapshot / graph version
- included node and edge IDs
- deterministic serialization order
- the exact before/after message payload produced by the client/harness
- transformation applied (
source_prune, descendant removal, replay, etc.)
- hash of that effective request
I would say client-observed request payload rather than assume that an OpenAI-compatible provider internally serializes it exactly the same way; the latter is often outside the experimenter’s visibility.
Model/runtime
- provider and endpoint
- exact model ID/revision when available
- tokenizer/chat-template revision for local models
- inference backend/version if local
- quantization if applicable
- temperature/top-p/seed and reasoning-mode settings
- timestamp
Execution
- raw response
- input/output token counts
- termination/finish reason
- whether the generation hit
max_new_tokens
- latency
- request ID if the provider supplies one
- retries/fallbacks/errors
Evaluation
- expected answer
- scorer/parser version
- raw parsed value
- automated score
- whether a failure was manually inspected
That last layer ended up being more important than I expected.
I tried a small matched-control run against the repair fixtures, and my first automated summary contained three apparent failures that were not actually context failures. All three outputs hit max_new_tokens=64; the model had already computed the correct answer in prose, but the required final-number line was cut in the middle of the number.
I reran the exact same pinned payloads at 64 and 128 tokens. The old 64-token strings reproduced exactly and were prefixes of the 128-token generations; all three longer generations completed the correct answer.
So a small practical addition I would make to the trace format is:
hit_generation_cap
finish_reason
raw_response
parsed_answer
score
That makes it much harder for an evaluator artifact to masquerade as a context-repair failure.
The matched control I tried, including the scoring gotcha
I used the public repair fixtures from the experiment state at ThoughtDAG commit 281930b, with Qwen3-4B-Instruct-2507 on a T4 in 4-bit.
I added one condition:
neutral_matched
Starting from the exact compiled polluted request, I kept:
- the clean prefix,
- the final question,
- message roles,
- message count,
- message order,
- and the locations of the contaminated turns,
but replaced the pollution turn and the frozen contaminated descendant turns with unrelated, digit-free neutral text.
The replacement was matched message-by-message at the tokenizer level, and I then checked the complete rendered chat-template length.
Result:
polluted vs neutral_matched
full chat-template token parity: 27/27
maximum token-count difference: 0
The clean condition was correct on all 27 cases.
The contaminated condition derailed 18 of them.
My initial automated result on those 18 derailed cases was:
neutral_matched 16/18
source_prune 13/18
subgraph_prune 18/18
But the two neutral failures and one source-prune failure all stopped at exactly 64 output tokens.
The three raw outputs had already done the correct arithmetic; only the requested final answer line was truncated.
So I made a second, deliberately tiny confirmation run:
same exact payload
same pinned model revision
64 tokens
vs
128 tokens
For all three:
input-token count reproduced exactly
old 64-token output reproduced exactly
64-token output was a prefix of 128-token output
128-token output completed the gold answer
So the corrected interpretation is:
among clean-correct + polluted-wrong cases:
neutral_matched 18/18
source_prune 14/18
subgraph_prune 18/18
I would not read 18/18 as a general model statistic: the 27 fixtures are related families with k=1/2/3 propagation variants, not 27 fully independent replications.
But I do think the matched-neutral comparison says something useful.
For this model/configuration and these fixtures, the failure is hard to explain as merely:
“the polluted request had more tokens”
because the neutral request had the same rendered token count.
It also weakens a simple:
“there were extra message slots”
explanation, because those slots remained too.
The narrower statement I think is supported is:
the semantic content of the contaminated chain mattered beyond matching its rendered token length and message-slot structure in this run.
There are still unmatched dimensions. The neutral filler was intentionally artificial, so it did not match lexical distribution, syntax, discourse naturalness, or semantic density. A fluent task-irrelevant matched control would be a stronger next version if that distinction becomes important.
Also, this neutral intervention replaced the contaminated chain, not just the original pollution source. So I would describe it as a chain-semantic control, not evidence that the source sentence alone was the causal unit.
2. I would keep “correction”, “detection”, and “repair” as separate problems
The question that originally motivated the post — is a later correction enough, or should the earlier source leave the request? — actually seems to contain several possible interventions:
append a correction
remove the bad source
remove affected descendants
recompute affected descendants
They are not interchangeable.
A later correction asks the model to perform something like belief revision while contradictory or superseded material remains available. There is already evidence that this is non-trivial: the Belief-R work on belief revision found that models often struggle to revise prior inferences appropriately when new evidence arrives.
But ThoughtDAG gives you another experimental lever: instead of asking the model to resolve the conflict internally, you can alter the effective context before the request.
That makes a useful separation possible:
A. Which state is actually stale / wrong?
↓
B. Once it is known to be wrong, what must be invalidated?
↓
C. What, if anything, must be recomputed?
I would treat A as a detection/adjudication benchmark and B/C as a repair benchmark.
That seems especially helpful for the temporal cases. If the latest turn says “the correction was wrong; go back to the old value”, the model may have no independent evidence telling it that the latest turn itself is false. Calling that a failure to detect misinformation would require a different source of truth.
Calling the branch known-bad by the experiment and then asking what repair is necessary avoids that ambiguity.
This is also starting to show up as a distinct neighboring problem in recent agent-memory work. STALE separates state resolution from downstream policy adaptation, and the very recent Dependency-Guided Rollback Repair explicitly assumes diagnosed faulty memories and asks how to retract affected downstream state while preserving unaffected work.
I would not treat those papers as proving the ThoughtDAG result — the systems and memory semantics are different — but the decomposition is strikingly similar.
It gives a reasonably standard vocabulary for what your source/subgraph/replay comparison is probing:
fault diagnosis
!=
fault removal
!=
dependency invalidation
!=
selective recomputation
That is probably a stronger framing than trying to make the one-edge result carry all four claims.
3. Source pruning and descendant cleanup look worth keeping separate
This was also the part of my small run I found most interesting after the matched-length question was controlled.
Among the 18 cases where pollution changed a clean-correct answer:
source-only pruning 14/18
contaminated subgraph 18/18
Again, one model and a small controlled fixture set, so I would not generalize the rate.
But it is consistent with a simple structural failure mode:
bad source
↓
derived claim
↓
derived calculation
↓
summary / recommendation
Once the derived state has been materialized into later messages, deleting only the original source does not necessarily remove the stale downstream text from the next request.
That makes the existing distinction between source pruning, subgraph pruning, and replay/recomputation useful in its own right.
There is also a nice design trade-off here:
- source-only removal preserves the most work, but can leave stale descendants;
- deleting the whole contaminated subgraph is conservative, but may throw away useful derived work;
- selective recomputation can potentially recover useful work under corrected premises, at additional compute cost.
So rather than asking only:
“Does pruning work?”
I would probably preserve the more informative question:
What is the smallest repair that restores a valid downstream state without unnecessarily discarding unaffected work?
That seems compatible with the direction ThoughtDAG is already taking with staleness and dependency-order replay.
4. Manual vs automatic looks like a control-plane question, not a winner-takes-all benchmark
I would be hesitant to turn this into:
manual pruning vs RAG
which one is better?
because they optimize different things.
A rough split might be:
| Mode |
Natural strength |
Natural cost |
| Manual |
inspectability, deliberate exceptions, debugging, research interventions, auditability |
human attention |
| Automatic |
routine operation, scale, low interaction cost |
false keeps / false removals can be less visible |
| Hybrid |
system does routine selection; human can inspect/override important cases |
more UI/control-plane complexity |
The distinction between stored history and effective model input is already a practical implementation primitive. For example, the OpenAI Agents SDK exposes model-input filtering, and Claude context editing separates selective clearing from broader compaction.
So I do not think the interesting claim for ThoughtDAG needs to be:
“other systems cannot filter context.”
The more distinctive question seems to be:
What changes when context selection is visible, reversible, and expressed in the same graph the human is using to reason?
That gives manual control a possible value even when automatic selection is perfectly available.
It also suggests a fairly natural third condition if you ever want to study this:
automatic suggestion
+
human-visible accept / reject / override
Recent work on controllable memory use points in a similar direction. For example, SteeM studies user control over how strongly an agent should rely on memory, rather than assuming maximum memory use is always desirable.
Another separation I like here is:
keep this history?
!=
show it to the human?
!=
include it in this model call?
Your current “remove the edge without deleting the earlier work” behavior is useful precisely because those do not have to be the same decision.
A possible evaluation matrix for manual / automatic / hybrid
If this ever becomes an HCI/control-plane experiment, I would not use answer accuracy as the only metric.
I would probably look at something like:
| Axis |
Why it matters |
| task accuracy |
Did the final answer recover? |
| false keep |
Did stale/irrelevant material remain active? |
| false removal |
Did useful context get discarded? |
| recovery time / operations |
How expensive was repair for the user/system? |
| token/call cost |
What did selective repair save or add? |
| reversibility |
Can an incorrect pruning decision be undone? |
| inspectability |
Can the user see what is active and why? |
| intervention agreement |
Do humans and the automatic selector choose the same removals? |
That turns “manual vs automatic” into a measurable trade-off rather than a philosophical preference.
A hybrid condition could also be tested without building a fully autonomous memory system first:
system marks suspected stale branches
human chooses:
keep
exclude for this request
invalidate descendants
recompute descendants
The useful result could be that automation wins almost everywhere. Or that human override only matters for a narrow class of conflicts. Either outcome would answer the broader question more cleanly than assuming in advance that visible control must be superior.
5. Yes to cross-model/context testing — but I would separate four variables
I think this is worth testing across models and larger contexts.
I would just distinguish nominal context capacity from actual input length.
An 800-token experiment on a model advertised as 128K context is still an ~800-token experiment; changing the model’s maximum window does not by itself test long-context behavior.
There are at least four variables that can otherwise get mixed together:
semantic treatment
position
actual input length
model / backend
The first cheap sequence I would use is probably:
-
semantic control
clean / polluted / matched-neutral / repaired
-
position control
move the same contaminated material earlier / middle / later while holding content as fixed as possible
-
actual length control
increase real input length while preserving the intervention
-
model/backend replication
then repeat a small selected panel across deliberately different model families/runtimes
There is good reason to isolate 2 and 3. Lost in the Middle showed that the position of relevant information can strongly affect long-context performance, while Context Length Alone Hurts LLM Performance Despite Perfect Retrieval found degradation from increasing input length even when retrieval of the relevant evidence was effectively controlled.
So if an edge deletion changes both content and where everything else lands in the request, those are alternative explanations worth keeping visible.
The matched-neutral condition is one cheap way of removing a large part of that ambiguity before paying for a large model sweep.
A compact decision tree I would use when reading the results
Does polluted perform worse than clean?
│
├─ no
│ └─ this case does not demonstrate pollution harm
│
└─ yes
│
├─ does token/structure-matched neutral also fail?
│ │
│ ├─ yes
│ │ └─ generic context / position / structure effects
│ │ remain plausible
│ │
│ └─ no
│ └─ contaminated semantic content becomes
│ a stronger explanation
│
└─ does source-only pruning recover?
│
├─ yes
│ └─ source removal was sufficient in this case
│
└─ no
│
├─ subgraph removal / replay recovers
│ └─ stale descendant state is a plausible
│ operational explanation
│
└─ none recover
└─ inspect:
- serialization/order
- position
- generation cap
- scorer/parser
- stochasticity
- backend/model revision
- gold label
I like this because every branch suggests a next check without requiring one explanation to be assumed in advance.
6. I would keep the causal wording at the level you already use: an input intervention
One thing I think the original post gets right is explicitly saying that this is not attention visualization or an explanation of why a particular token was generated.
An edge here establishes something concrete:
an upstream node was or was not serialized into the downstream request.
That is a useful provenance/exposure relation.
It does not automatically establish:
every statement in the child is semantically dependent on that parent,
or:
the model internally represented that graph edge as the cause.
There is a nearby research vocabulary for this. ContextCite, for example, treats context attribution as a perturbation problem: alter subsets of the context and measure what happens to generation.
So I would be comfortable calling the ThoughtDAG operation an observable context intervention or a counterfactual context ablation.
That is already useful without promoting it into a hidden-mechanism explanation.
7. If you expand the benchmark, I would diversify the dependency shape before making it huge
The current controlled arithmetic cases are useful because they make the intervention easy to audit.
The trade-off is that many of them share a similar computational shape.
So, if the next goal is generalization, I am not sure the highest-information next step is simply “more models × more nearly identical arithmetic cases.”
A small number of different dependency motifs might tell you more:
ratio / division
conditional choice
lookup → transformation
multi-source aggregation
multi-step plan with a reusable intermediate result
The especially interesting cases for replay would be ones where a descendant contains useful work that should not simply be thrown away.
That would separate:
“delete everything downstream and solve the easy final arithmetic again”
from:
“invalidate exactly the work that depended on the bad premise, then reconstruct the useful intermediate state.”
For a later natural-language track, something like LongMemEval gives useful categories such as multi-session reasoning, temporal reasoning, and knowledge updates. I would keep that as a separate generalization lane rather than weakening the controlled synthetic lane by trying to make one benchmark do both jobs.
8. One lane in the current pilot may be best described as a negative control
In my Qwen run, the explicitly irrelevant-distractor cases produced:
0/9 derailments
while the misinformation and temporal-supersession families each derailed all nine of their tested k=1/2/3 cases.
Given how explicitly the fixtures identify those asides as unrelated, I would personally read that lane as a useful negative control / sanity check:
these clearly marked irrelevant asides did not land in this short controlled setup.
I would not generalize it to:
irrelevant context is harmless.
That distinction also keeps it compatible with the broader long-context literature, where irrelevant material and length can certainly hurt under other conditions.
9. A future boundary if graph pruning reaches tool calls
This is not a problem with the current text-only intervention, but it may matter as ThoughtDAG grows more agentic.
Some model APIs impose structural constraints on conversation history. A tool invocation and its result, for example, may have to remain paired in a particular order. Arbitrarily removing one message can make the remaining request invalid rather than merely changing its semantics.
So a future graph may need the notion of an atomic pruning unit or protocol-aware context transformation:
semantic node
vs
provider-valid message unit
That is probably only worth worrying about when tool traces themselves become editable context, but it seems like a useful boundary to keep in mind.
Putting all of that together, I think the result is already more interesting than:
“I removed an edge and the answer changed.”
The more specific experiment I see is:
Given a context state that is known to contain a contaminated branch, what is the smallest observable context intervention that restores a correct downstream state, and what useful work can be preserved?
That gives you several cleanly separable research questions without requiring the UI, the memory policy, the misinformation detector, and the model’s hidden reasoning to all be evaluated at once.
And for the broader human-vs-system question, I would keep the thing that seems genuinely distinctive here: the branch can remain part of the visible history while being excluded from the active model request.
That means the design does not force remembering, showing, and using right now to be the same operation.
To me, that is probably the most interesting place to compare human-directed, automatic, and hybrid context control.