@mmerterden/multi-agent-pipeline 15.10.0 → 15.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,12 @@ Internal file-layout changes that don't affect the slash-command surface are sti
|
|
|
16
16
|
|
|
17
17
|
## [Unreleased]
|
|
18
18
|
|
|
19
|
+
## [15.10.1] - 2026-08-21
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- **`uninstall --all-data` now removes the per-repo memory root.** `~/.claude/memory/multi-agent/` holds the learnings ledger and triage corpus: durable knowledge written in prose about the repos it was collected from, which on a corporate checkout is concrete information about the codebase. It survived even the full-cleanup mode, so "removes everything but your tokens" was not true in the one place a user is most likely to mean it. The default run still keeps it, alongside settings and logs, and both halves of that promise are now tested.
|
|
23
|
+
- **Offloaded tool payloads are reclaimable.** v15.10.0 added `offload-ref.sh` without a way to clean up after it. In worktree modes the payloads die with the worktree, but the `--local` modes write into the real checkout, and because `.multi-agent/refs/` is gitignored the files never appear in `git status` and nothing reclaims them. New `gc-refs.sh`, dispatched as a third phase of `/multi-agent:garbage-collect`, sweeps them with the same contract as the /tmp sweeper: dry-run until `--yes`, a root guard that refuses `/` and `$HOME`, a grace window so a sweep cannot pull a ref out from under a running phase, and node-id matching so a file the user put in that directory survives. `--all` sweeps every checkout under `$HOME`.
|
|
24
|
+
|
|
19
25
|
## [15.10.0] - 2026-08-21
|
|
20
26
|
|
|
21
27
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mmerterden/multi-agent-pipeline",
|
|
3
|
-
"version": "15.10.
|
|
3
|
+
"version": "15.10.1",
|
|
4
4
|
"description": "8-phase AI development pipeline with full orchestration on Claude Code, Copilot CLI and Codex CLI. Analysis, planning, TDD, CLI-aware parallel review with consensus surfacing + Fable triage, default-FAIL evidence gates, secret + intent guards, per-phase cost ledger, persistent learnings memory, wiki generation, commit automation. Token-preserving uninstall.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Sweep leftover /tmp scratch (picker state, review diffs, channel payloads, analysis drafts)
|
|
3
|
-
description-tr: "Geçmiş çalışmalardan kalan /tmp scratch'ini (picker durumu, review diff'leri, kanal payload'ları, analiz taslakları)
|
|
2
|
+
description: "Sweep leftover /tmp scratch (picker state, review diffs, channel payloads, analysis drafts), worktree residue (orphan .worktrees dirs, gitlink index entries) and offloaded tool payloads under .multi-agent/refs/ from past runs. Dry-run first; confirms before deleting. Use when scratch files from earlier runs need clearing out."
|
|
3
|
+
description-tr: "Geçmiş çalışmalardan kalan /tmp scratch'ini (picker durumu, review diff'leri, kanal payload'ları, analiz taslakları), worktree kalıntılarını (sahipsiz .worktrees klasörleri, gitlink index kayıtları) ve .multi-agent/refs/ altındaki offload edilmiş araç çıktılarını süpürür. Önce dry-run; silmeden önce onay alır."
|
|
4
4
|
argument-hint: "[--older-than=<minutes>] [--yes] - dry-run unless confirmed"
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -72,6 +72,31 @@ deletes nothing until you confirm.
|
|
|
72
72
|
- On confirm, re-run with `--yes` and echo its summary line. If a gitlink
|
|
73
73
|
was unstaged, remind the user the removal still needs a commit.
|
|
74
74
|
|
|
75
|
+
7. **Offloaded payload sweep (third phase)** - when the current directory is a
|
|
76
|
+
git repo, also preview the offloaded tool payloads:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
bash $HOME/.claude/scripts/gc-refs.sh ${ARGUMENTS}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`offload-ref.sh` parks build logs, diffs and test output under
|
|
83
|
+
`.multi-agent/refs/<node_id>.md`. In worktree modes that directory dies with
|
|
84
|
+
the worktree; in the `--local` modes it lands in the real checkout, and
|
|
85
|
+
because it is gitignored it never shows up in `git status`. Only files
|
|
86
|
+
matching the node-id shape are touched - anything else in that directory is
|
|
87
|
+
left alone, and files inside the grace window are spared so a sweep cannot
|
|
88
|
+
pull a ref out from under a running phase.
|
|
89
|
+
|
|
90
|
+
- Output says `nothing to do` -> skip silently, no question.
|
|
91
|
+
- Otherwise surface a third `AskUserQuestion` (in `outputLanguage`):
|
|
92
|
+
`question`: "Delete the listed offloaded payloads?" (include the count and
|
|
93
|
+
freed size), `header`: "Payloads", options `{ label: "Delete payloads" }` /
|
|
94
|
+
`{ label: "Cancel", description: "Keep everything, change nothing" }`.
|
|
95
|
+
- On confirm, re-run with `--yes` and echo its summary line.
|
|
96
|
+
|
|
97
|
+
Pass `--all` to sweep every checkout under `$HOME` rather than only the
|
|
98
|
+
current repo.
|
|
99
|
+
|
|
75
100
|
## Notes
|
|
76
101
|
|
|
77
102
|
- An in-flight analysis keeps its drafts in `/tmp/analysis-<slug>-<timestamp>/`
|
|
@@ -79,6 +104,10 @@ deletes nothing until you confirm.
|
|
|
79
104
|
`awaiting_output_decision`, pass `--older-than=<minutes>` so fresh drafts are
|
|
80
105
|
spared, or finish the run first.
|
|
81
106
|
- The /tmp phase only touches `/tmp` scratch; the worktree phase only touches
|
|
82
|
-
the current repo's `.worktrees/` residue and index
|
|
107
|
+
the current repo's `.worktrees/` residue and index; the payload phase only
|
|
108
|
+
touches node-id files under `.multi-agent/refs/`. Persistent per-task logs
|
|
83
109
|
live under `~/.claude/logs/multi-agent/` and are cleaned by
|
|
84
|
-
`/multi-agent:prune-logs`.
|
|
110
|
+
`/multi-agent:prune-logs`. The per-repo memory stores under
|
|
111
|
+
`~/.claude/memory/multi-agent/` are durable knowledge, not scratch: they are
|
|
112
|
+
removed only by `/multi-agent:uninstall --all-data`, or one entry at a time
|
|
113
|
+
with `learnings-ledger.mjs forget`.
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# gc-refs.sh - remove offloaded tool payloads left behind in a repo checkout.
|
|
3
|
+
#
|
|
4
|
+
# `offload-ref.sh` parks build logs, diffs and test output under
|
|
5
|
+
# <root>/.multi-agent/refs/<node_id>.md so a phase prompt can carry a pointer
|
|
6
|
+
# instead of the whole log. In worktree modes that directory dies with the
|
|
7
|
+
# worktree. In the --local modes there is no worktree: the refs land in the
|
|
8
|
+
# real checkout and nothing ever removes them. They are gitignored, so they are
|
|
9
|
+
# invisible to `git status` and grow without bound.
|
|
10
|
+
#
|
|
11
|
+
# This sweeps them, with the same safety contract as gc-tmp.sh:
|
|
12
|
+
# - dry-run by default: lists what WOULD be removed and the space it frees,
|
|
13
|
+
# and deletes nothing until --yes
|
|
14
|
+
# - root guard: refuses a root that is not a directory, and refuses $HOME
|
|
15
|
+
# and / outright, so a stray GC_REFS_ROOT cannot sweep a home directory
|
|
16
|
+
# - fresh-payload grace: files touched in the last GC_REFS_GRACE_MIN minutes
|
|
17
|
+
# (default 10) are spared, so a sweep during an in-flight run cannot pull a
|
|
18
|
+
# ref out from under the agent that is about to read it
|
|
19
|
+
#
|
|
20
|
+
# Only files matching the node-id shape are touched; anything else a user put
|
|
21
|
+
# in that directory is left alone.
|
|
22
|
+
#
|
|
23
|
+
# Usage:
|
|
24
|
+
# gc-refs.sh # dry-run over the current repo
|
|
25
|
+
# gc-refs.sh --yes # actually delete
|
|
26
|
+
# gc-refs.sh --older-than=1440 # only payloads older than a day
|
|
27
|
+
# gc-refs.sh --all # every repo under GC_REFS_SEARCH (default $HOME)
|
|
28
|
+
#
|
|
29
|
+
# Env:
|
|
30
|
+
# GC_REFS_ROOT override the repo root (default: git toplevel, else $PWD)
|
|
31
|
+
# GC_REFS_SEARCH where --all looks for checkouts (default $HOME)
|
|
32
|
+
# GC_REFS_GRACE_MIN grace window in minutes (default 10, 0 = off)
|
|
33
|
+
#
|
|
34
|
+
# Exit: 0 on success or nothing to do, 2 on usage error or a refused root.
|
|
35
|
+
|
|
36
|
+
set -uo pipefail
|
|
37
|
+
|
|
38
|
+
GRACE_MIN="${GC_REFS_GRACE_MIN:-10}"
|
|
39
|
+
SEARCH_ROOT="${GC_REFS_SEARCH:-$HOME}"
|
|
40
|
+
DELETE=0
|
|
41
|
+
OLDER_MIN=0
|
|
42
|
+
ALL=0
|
|
43
|
+
|
|
44
|
+
usage() {
|
|
45
|
+
grep -E '^#( |$)' "$0" | sed -E 's/^# ?//'
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
for arg in "$@"; do
|
|
49
|
+
case "$arg" in
|
|
50
|
+
--yes | --force) DELETE=1 ;;
|
|
51
|
+
--all) ALL=1 ;;
|
|
52
|
+
--older-than=*)
|
|
53
|
+
OLDER_MIN="${arg#*=}"
|
|
54
|
+
if ! printf '%s' "$OLDER_MIN" | grep -qE '^[0-9]+$'; then
|
|
55
|
+
echo "gc-refs: --older-than needs a whole number of minutes, got: $OLDER_MIN" >&2
|
|
56
|
+
exit 2
|
|
57
|
+
fi
|
|
58
|
+
;;
|
|
59
|
+
-h | --help)
|
|
60
|
+
usage
|
|
61
|
+
exit 0
|
|
62
|
+
;;
|
|
63
|
+
*)
|
|
64
|
+
echo "gc-refs: unknown argument: $arg" >&2
|
|
65
|
+
exit 2
|
|
66
|
+
;;
|
|
67
|
+
esac
|
|
68
|
+
done
|
|
69
|
+
|
|
70
|
+
if ! printf '%s' "$GRACE_MIN" | grep -qE '^[0-9]+$'; then
|
|
71
|
+
echo "gc-refs: GC_REFS_GRACE_MIN needs a whole number of minutes, got: $GRACE_MIN" >&2
|
|
72
|
+
exit 2
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# Collect the refs directories to consider.
|
|
76
|
+
REFS_DIRS=""
|
|
77
|
+
if [ "$ALL" -eq 1 ]; then
|
|
78
|
+
if [ ! -d "$SEARCH_ROOT" ]; then
|
|
79
|
+
echo "gc-refs: no search root at $SEARCH_ROOT - nothing to do"
|
|
80
|
+
exit 0
|
|
81
|
+
fi
|
|
82
|
+
# Prune the trees that are large and never hold a pipeline checkout, so a
|
|
83
|
+
# home-wide sweep stays seconds rather than minutes.
|
|
84
|
+
REFS_DIRS=$(find "$SEARCH_ROOT" \
|
|
85
|
+
\( -name node_modules -o -name Pods -o -name .build -o -name DerivedData -o -name .next \) -prune \
|
|
86
|
+
-o -type d -path "*/.multi-agent/refs" -print 2>/dev/null)
|
|
87
|
+
else
|
|
88
|
+
ROOT="${GC_REFS_ROOT:-}"
|
|
89
|
+
if [ -z "$ROOT" ]; then
|
|
90
|
+
ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
|
|
91
|
+
[ -n "$ROOT" ] || ROOT="$PWD"
|
|
92
|
+
fi
|
|
93
|
+
# Root guard: never accept a root that resolves to / or $HOME. A sweep is
|
|
94
|
+
# recursive and a mistyped override should not be able to reach a home dir.
|
|
95
|
+
case "$ROOT" in
|
|
96
|
+
/ | "$HOME")
|
|
97
|
+
echo "gc-refs: refusing to sweep '$ROOT' - point GC_REFS_ROOT at a repo checkout" >&2
|
|
98
|
+
exit 2
|
|
99
|
+
;;
|
|
100
|
+
esac
|
|
101
|
+
[ -d "$ROOT" ] || {
|
|
102
|
+
echo "gc-refs: no directory at $ROOT - nothing to do"
|
|
103
|
+
exit 0
|
|
104
|
+
}
|
|
105
|
+
[ -d "$ROOT/.multi-agent/refs" ] && REFS_DIRS="$ROOT/.multi-agent/refs"
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
if [ -z "$REFS_DIRS" ]; then
|
|
109
|
+
echo "gc-refs: no offloaded payloads found - nothing to do"
|
|
110
|
+
exit 0
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# Match the node-id shape offload-ref.sh writes (p<phase>-<slug>-<8 hex>.md).
|
|
114
|
+
# Anything else in that directory belongs to someone else.
|
|
115
|
+
NODE_GLOB='p*-*-*.md'
|
|
116
|
+
|
|
117
|
+
MATCHES=""
|
|
118
|
+
while IFS= read -r dir; do
|
|
119
|
+
[ -n "$dir" ] || continue
|
|
120
|
+
# `-mmin +0` is not a no-op: it means "older than a minute" and would drop a
|
|
121
|
+
# file written seconds ago. The age filter is applied only when one was asked
|
|
122
|
+
# for; the grace window below is what protects an in-flight payload.
|
|
123
|
+
if [ "$OLDER_MIN" -gt 0 ]; then
|
|
124
|
+
found=$(find "$dir" -maxdepth 1 -type f -name "$NODE_GLOB" -mmin +"$OLDER_MIN" 2>/dev/null)
|
|
125
|
+
else
|
|
126
|
+
found=$(find "$dir" -maxdepth 1 -type f -name "$NODE_GLOB" 2>/dev/null)
|
|
127
|
+
fi
|
|
128
|
+
[ -n "$found" ] || continue
|
|
129
|
+
while IFS= read -r f; do
|
|
130
|
+
[ -n "$f" ] || continue
|
|
131
|
+
# Grace: skip anything touched inside the window.
|
|
132
|
+
if [ "$GRACE_MIN" -gt 0 ] && [ -n "$(find "$f" -mmin -"$GRACE_MIN" 2>/dev/null)" ]; then
|
|
133
|
+
continue
|
|
134
|
+
fi
|
|
135
|
+
MATCHES="$MATCHES$f
|
|
136
|
+
"
|
|
137
|
+
done <<EOF
|
|
138
|
+
$found
|
|
139
|
+
EOF
|
|
140
|
+
done <<EOF
|
|
141
|
+
$REFS_DIRS
|
|
142
|
+
EOF
|
|
143
|
+
|
|
144
|
+
MATCHES=$(printf '%s' "$MATCHES" | grep -v '^$' || true)
|
|
145
|
+
if [ -z "$MATCHES" ]; then
|
|
146
|
+
echo "gc-refs: no offloaded payloads outside the grace window - nothing to do"
|
|
147
|
+
exit 0
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
COUNT=$(printf '%s\n' "$MATCHES" | grep -c .)
|
|
151
|
+
BYTES=0
|
|
152
|
+
while IFS= read -r f; do
|
|
153
|
+
[ -n "$f" ] || continue
|
|
154
|
+
sz=$(wc -c < "$f" 2>/dev/null | tr -d ' ')
|
|
155
|
+
BYTES=$((BYTES + ${sz:-0}))
|
|
156
|
+
done <<EOF
|
|
157
|
+
$MATCHES
|
|
158
|
+
EOF
|
|
159
|
+
KB=$(((BYTES + 1023) / 1024))
|
|
160
|
+
|
|
161
|
+
if [ "$DELETE" -eq 0 ]; then
|
|
162
|
+
echo "gc-refs: would remove $COUNT offloaded payload(s), freeing ${KB} KB"
|
|
163
|
+
printf '%s\n' "$MATCHES" | sed 's/^/ /'
|
|
164
|
+
echo ""
|
|
165
|
+
echo "Nothing deleted. Re-run with --yes to remove them."
|
|
166
|
+
exit 0
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
removed=0
|
|
170
|
+
while IFS= read -r f; do
|
|
171
|
+
[ -n "$f" ] || continue
|
|
172
|
+
rm -f "$f" && removed=$((removed + 1))
|
|
173
|
+
done <<EOF
|
|
174
|
+
$MATCHES
|
|
175
|
+
EOF
|
|
176
|
+
|
|
177
|
+
# Drop a refs directory that is now empty; leave one that still holds
|
|
178
|
+
# something we did not put there.
|
|
179
|
+
while IFS= read -r dir; do
|
|
180
|
+
[ -n "$dir" ] || continue
|
|
181
|
+
rmdir "$dir" 2>/dev/null || true
|
|
182
|
+
done <<EOF
|
|
183
|
+
$REFS_DIRS
|
|
184
|
+
EOF
|
|
185
|
+
|
|
186
|
+
echo "gc-refs: removed $removed offloaded payload(s), freed ${KB} KB"
|
|
187
|
+
exit 0
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
* Preserved by default, removed with --all-data:
|
|
32
32
|
* - $HOME/.claude/multi-agent-preferences.json (pipeline settings)
|
|
33
33
|
* - $HOME/.claude/logs/multi-agent/ (task logs, state, metrics, audit trail)
|
|
34
|
+
* - $HOME/.claude/memory/multi-agent/ (per-repo learnings ledger + triage corpus)
|
|
34
35
|
*
|
|
35
36
|
* @module pipeline/scripts/runtime/uninstall
|
|
36
37
|
*/
|
|
@@ -635,6 +636,7 @@ export async function main() {
|
|
|
635
636
|
console.log(" FULL CLEANUP (--all-data) also removes:");
|
|
636
637
|
console.log(" - ~/.claude/multi-agent-preferences.json (pipeline settings)");
|
|
637
638
|
console.log(" - ~/.claude/logs/multi-agent/ (task logs, state, metrics, audit trail)");
|
|
639
|
+
console.log(" - ~/.claude/memory/multi-agent/ (per-repo learnings ledger + triage corpus)");
|
|
638
640
|
console.log("");
|
|
639
641
|
}
|
|
640
642
|
console.log(" PRESERVED (never touched):");
|
|
@@ -733,14 +735,22 @@ export async function main() {
|
|
|
733
735
|
stripManagedBlock(join(COP, "copilot-instructions.md"));
|
|
734
736
|
}
|
|
735
737
|
|
|
736
|
-
// Full cleanup: pipeline settings
|
|
737
|
-
// pipeline-generated data (not user-authored like
|
|
738
|
-
// --all-data removes them; the default run leaves them
|
|
738
|
+
// Full cleanup: pipeline settings, the log root, and the per-repo memory
|
|
739
|
+
// stores. All three are pipeline-generated data (not user-authored like
|
|
740
|
+
// CLAUDE.md / rules), so --all-data removes them; the default run leaves them
|
|
741
|
+
// in place.
|
|
742
|
+
//
|
|
743
|
+
// The memory root was missing here, and it is the one a user is most likely
|
|
744
|
+
// to mean by "remove everything": the learnings ledger and triage corpus hold
|
|
745
|
+
// architectural facts and past review findings written in prose about the
|
|
746
|
+
// repos they were collected from. On a corporate checkout that is concrete
|
|
747
|
+
// information about the codebase, and it survived even --all-data.
|
|
739
748
|
if (allData && HOME) {
|
|
740
749
|
console.log("");
|
|
741
|
-
console.log(" [Full cleanup] Removing pipeline settings +
|
|
750
|
+
console.log(" [Full cleanup] Removing pipeline settings, logs + memory...");
|
|
742
751
|
rmIfExists(join(HOME, ".claude", "multi-agent-preferences.json"));
|
|
743
752
|
rmIfExists(join(HOME, ".claude", "logs", "multi-agent"));
|
|
753
|
+
rmIfExists(join(HOME, ".claude", "memory", "multi-agent"));
|
|
744
754
|
}
|
|
745
755
|
|
|
746
756
|
// Legacy adapter-file cleanup (adapters removed in v10.7.0). These blocks
|
|
@@ -818,7 +828,7 @@ export async function main() {
|
|
|
818
828
|
if (!allData) {
|
|
819
829
|
console.log("");
|
|
820
830
|
console.log(
|
|
821
|
-
" Kept your pipeline settings +
|
|
831
|
+
" Kept your pipeline settings, logs + per-repo memory. To remove those too, re-run with --all-data.",
|
|
822
832
|
);
|
|
823
833
|
} else {
|
|
824
834
|
console.log("");
|