A removal of a replacement names both fingerprints; the two-texts refusal names the places and the way out

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-05 23:19:03 +01:00
parent 80f992e367
commit aa7c9e8924
2 changed files with 31 additions and 12 deletions
@@ -215,6 +215,11 @@ func (p Proposal) glanceAsk() oc.Ask {
}
fmt.Fprintf(&d, "Proposed through the claude-code module on %s at %s UTC. %s has the fingerprint %s.",
p.From, p.At.UTC().Format("15:04 on 2 Jan"), removes, print)
if p.Over != "" && p.Digest != p.Over {
// A replacement is removed with the registered text it stands over: both fingerprints, the replacement's
// being the text sessions read.
fmt.Fprintf(&d, " The replacement sessions read, which it also removes, has the fingerprint %s.", p.Fingerprint())
}
} else {
if whole {
d.WriteString("The text:\n" + shown + "\n")
@@ -1352,25 +1357,33 @@ func registeredSection(p Paths, scope string, nodes []string, name string) (stri
_ = readJSON(p.config(), &items)
c := ConfigOf(Taken(items))
c.Terminal, _ = terminalText(p)
layers := [][]Item{c.Mesh, c.Terminal}
type place struct {
items []Item
says string
}
places := []place{{c.Mesh, "registered for the mesh (unregister it with claude_code_instructions_unregister, scope mesh, name " + name + ")"},
{c.Terminal, "set at the controller's terminal (its instructions setting)"}}
if scope == ScopeNode {
layers = [][]Item{c.Node, c.Terminal}
places = []place{{c.Node, "registered for this node (unregister it with claude_code_instructions_unregister, scope node, name " + name + ")"},
{c.Terminal, "set at the controller's terminal (its instructions setting)"}}
if !contains(nodes, p.Node) {
layers = [][]Item{c.Terminal}
places = places[1:]
}
}
digest := ""
for _, layer := range layers {
for _, it := range layer {
var holding []string
for _, pl := range places {
for _, it := range pl.items {
if it.Kind != KindInstructions || it.Name != name {
continue
}
d := textDigest(it.Files[name+".md"])
if digest != "" && d != digest {
return "", fmt.Errorf("the section %q is registered with different texts (for the mesh and at the controller's terminal); "+
"remove one of them first", name)
return "", fmt.Errorf("the section %q is registered with different texts: %s and %s; an approval is bound to one text, "+
"so unregister one of them first", name, strings.Join(holding, ", "), pl.says)
}
digest = d
holding = append(holding, pl.says)
}
}
return digest, nil
@@ -190,7 +190,9 @@ func TestRegisteredSectionEdgeCases(t *testing.T) {
writeFile(t, p.Settings, string(raw))
store, r := &memProposals{m: map[string]json.RawMessage{}}, newRouter()
in := ProposeInput{Scope: ScopeMesh, Name: name, Text: "A third text.\n"}
if _, err := Propose(p, in, store, r, t0); err == nil || !strings.Contains(err.Error(), "different texts") {
if _, err := Propose(p, in, store, r, t0); err == nil || !strings.Contains(err.Error(), "different texts") ||
!strings.Contains(err.Error(), "claude_code_instructions_unregister, scope mesh, name "+name) ||
!strings.Contains(err.Error(), "set at the controller's terminal") {
t.Fatalf("a name registered with two texts was proposed over: %v", err)
}
if _, err := Propose(p, ProposeInput{Scope: ScopeMesh, Name: name, Remove: true}, store, r, t0); err == nil {
@@ -223,11 +225,11 @@ func TestRegisteredSectionEdgeCases(t *testing.T) {
if got := renderedInstructions(t, p); strings.Contains(got, "The old words.") || strings.Contains(got, "The new words.") {
t.Errorf("a text is left:\n%s", got)
}
// The ask names the registered text's fingerprint, not the replacement's.
// The ask names both fingerprints: the registered text's, and the replacement's that sessions read.
d := r.published[rid].Details
if !strings.Contains(d, "The registered text it removes has the fingerprint "+fingerprintOf(textDigest(registeredOld))) ||
strings.Contains(d, fingerprintOf(textDigest(registeredNew))) {
t.Errorf("the removal names the wrong fingerprint: %q", d)
!strings.Contains(d, "has the fingerprint "+fingerprintOf(textDigest(registeredNew))) {
t.Errorf("the removal does not name both fingerprints: %q", d)
}
})
t.Run("TestAChangedRegisteredTextOutlivesItsApproval", func(t *testing.T) {
@@ -248,9 +250,13 @@ func TestRegisteredSectionEdgeCases(t *testing.T) {
raw, _ := json.Marshal(map[string]Item{"mesh.instructions." + name: {Kind: KindInstructions, Name: name,
Scope: ScopeMesh, Files: one(name, "A later registered text.\n"), By: "g14"}})
writeFile(t, p.config(), string(raw))
if got := renderedInstructions(t, p); !strings.Contains(got, "A later registered text.") {
got := renderedInstructions(t, p)
if !strings.Contains(got, "A later registered text.") {
t.Errorf("the changed registered text was swallowed by the old approval:\n%s", got)
}
if !strings.Contains(got, "The new words.") || !strings.Contains(got, "## Instructions the operator approved") {
t.Errorf("the approved replacement does not render among the approved sections:\n%s", got)
}
})
t.Run("TestARemovalOfARemovedSectionIsRefused", func(t *testing.T) {
p, _ := node(t, "g14")