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:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user