claude-code: remove from or restore to only an agent account's own home
mesh/merge-gate pass: builds claude-code → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh, merge-check-typescript.sh): main's version judged it; the change's judges the pull r…
mesh/delivery delivered

Removing a rule from the operator's own home changes what their sessions
obey as surely as placing one: an agent could remove the rule that
constrains it (hq issue 340).
This commit is contained in:
jochen
2026-10-09 09:51:18 +02:00
parent 3677af6079
commit d984eb84d6
5 changed files with 66 additions and 7 deletions
@@ -61,7 +61,7 @@ func TestEveryKindIsShownInFull(t *testing.T) {
}
func TestARemovalNeedsItsReason(t *testing.T) {
p, _ := node(t, "laptop")
p, _ := confinedNode(t, "laptop")
dir := filepath.Join(p.Home, ".claude")
_ = os.MkdirAll(filepath.Join(dir, "rules"), 0o755)
writeFile(t, filepath.Join(dir, "rules", "keep.md"), "x")
@@ -74,7 +74,7 @@ func TestARemovalNeedsItsReason(t *testing.T) {
}
func TestARemovalKeepsACopyAndLogsWhy(t *testing.T) {
p, _ := node(t, "laptop")
p, _ := confinedNode(t, "laptop")
dir := filepath.Join(p.Home, ".claude")
_ = os.MkdirAll(filepath.Join(dir, "rules"), 0o755)
_ = os.MkdirAll(filepath.Join(dir, "skills", "old", "scripts"), 0o755)
@@ -144,7 +144,7 @@ func TestARemovalKeepsACopyAndLogsWhy(t *testing.T) {
}
func TestTheMemoryIsRemovedAndKept(t *testing.T) {
p, _ := node(t, "laptop")
p, _ := confinedNode(t, "laptop")
dir := filepath.Join(p.Home, ".claude")
writeFile(t, filepath.Join(dir, "CLAUDE.md"), "# HAL era\n")
answer, err := RemoveHome(p, KindMemory, "", "the managed file says it now", at)
@@ -185,7 +185,7 @@ func TestWhatTheMeshPlacedIsRefused(t *testing.T) {
}
func TestASymbolicLinkIsLeftAlone(t *testing.T) {
p, _ := node(t, "laptop")
p, _ := confinedNode(t, "laptop")
dir := filepath.Join(p.Home, ".claude")
elsewhere := t.TempDir()
writeFile(t, filepath.Join(elsewhere, "target.md"), "not the home's")
@@ -210,7 +210,7 @@ func TestASymbolicLinkIsLeftAlone(t *testing.T) {
}
func TestARemovalIsListedAndPutBack(t *testing.T) {
p, _ := node(t, "laptop")
p, _ := confinedNode(t, "laptop")
dir := filepath.Join(p.Home, ".claude")
_ = os.MkdirAll(filepath.Join(dir, "rules"), 0o755)
_ = os.MkdirAll(filepath.Join(dir, "skills", "old", "scripts"), 0o755)
@@ -275,7 +275,7 @@ func TestARemovalIsListedAndPutBack(t *testing.T) {
}
func TestACopyThatChangedIsNotPutBack(t *testing.T) {
p, _ := node(t, "laptop")
p, _ := confinedNode(t, "laptop")
dir := filepath.Join(p.Home, ".claude")
_ = os.MkdirAll(filepath.Join(dir, "rules"), 0o755)
_ = os.MkdirAll(filepath.Join(dir, "skills", "s"), 0o755)