1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! Prune the fork point's **inherited dialog** from a *child's* forked
//! tree, at its dispatch commit (ARCH §2.2, §2.3 step 2, §2.5).
//!
//! `messages/**`, `summary/**` and `skills/**` are branch-scoped context
//! (§2.2): written per-branch, never meant to become any other agent's
//! context. The work-product transfer enforces that child-to-parent
//! (§2.6, `transfer`'s excludes); this prune is the same invariant
//! parent-to-child, at the one place a tree crosses branches — the fork
//! ([`crate::prompt::subagent::spawn_subagent_branch`], every child
//! dispatch; never the root path, below).
//!
//! Without it, a child forked off its parent's tip carried the parent's
//! whole conversation as its own: assembly is a pure function of the
//! tree (§5.1) and the transcript composes unconditionally (§5.2), so
//! the parent's dialog — including user-role instructions addressed to
//! the *parent* — opened every child's first model call. The reproduced
//! runaway (litany bl-5a36, from yog bl-d023): a user told an agent
//! "spawn a subagent to analyze …"; the dispatched child inherited that
//! instruction as an apparently unanswered user message — the unsettled
//! prune ([`super::unsettled`]) had deleted the parent's `dispatch`
//! `tool_use`, the only evidence the spawn already happened — and it
//! outranked the child's own deposited goal, so the child obeyed it,
//! and every generation re-dispatched until the operator stopped the
//! tree. A child's opening context is its pinned goal, soul and pins
//! plus what is deposited to it — never its dispatcher's dialog.
//!
//! **Two principled exceptions, one axis: whose conversation is it?**
//!
//! - **A fork-back-in root keeps the dialog — it *is* its
//! conversation.** `litany prompt --from <ref>` re-enters a recorded
//! conversation at any commit (§7.2): the inherited transcript is the
//! very thing being resumed. That is why this prune is a part of the
//! child spawn, not of [`super::trim_to_context`] — the root's
//! dispatch commit must not run it.
//! - **A compactor keeps the dialog — it is its *subject*.** Its goal
//! is to compact the dispatching branch's history, delivered by fork
//! inheritance (§2.7: "its worktree carries that branch's transcript
//! … and it is composed from that tree"); the summary chain must stay
//! visible or a superseding summary destroys signal, and spent
//! `skills/**` bodies must stay nominable for deletion. The exception
//! is keyed on the role — the same signal the toolset injection and
//! checkpoint exclusion already branch on (§2.7).
//!
//! Total like the trim's parts: a child forked off a config commit
//! carries none of these paths, and `--ignore-unmatch` makes the
//! removal a no-op there rather than a special case.
use crateError;
use crateGitRunner;
use Path;
/// The branch-scoped dialog paths a child fork must not carry across
/// (§2.2): the transcript ([`crate::prompt::dispatch::MESSAGES_DIR`]),
/// the summary chain, the loaded skill bodies. `goal.md`, `soul.md` and
/// `name` complete the §2.6 branch-scoped set but are overwritten by
/// the dispatch commit itself, so they need no removal here.
const DIALOG_PATHS: & = &;
/// Stage the removal of the fork point's inherited dialog — for every
/// child role but the compactor, whose subject it is (module docs).
pub