claude-code: say what a registration wrote here, whichever took it first

On g14 the node's own watch took a home registration before the tool did,
and the answer said 'already so' though the file had just been placed.
Compare the view before and after, and render whenever the item applies
here, as the MCP server registration already does.
This commit is contained in:
jochen
2026-10-05 14:33:53 +02:00
parent 4f3e52b47a
commit 1fc10b0323
2 changed files with 25 additions and 5 deletions
+12 -5
View File
@@ -800,8 +800,10 @@ func Register(p Paths, it Item, nodes []string, unregister bool, state ConfigSta
}
}
}
// Compared before and after rather than read from Take: this node's own watch may take the same change
// first, and then Take here finds nothing new although this call made it.
before, _ := json.Marshal(v.Items())
var keys []string
changed := false
for _, n := range nodes {
key := it.Key(n)
keys = append(keys, key)
@@ -819,7 +821,12 @@ func Register(p Paths, it Item, nodes []string, unregister bool, state ConfigSta
op = "delete"
}
item := it
changed = v.Take(key, op, &item) || changed
v.Take(key, op, &item)
}
after, _ := json.Marshal(v.Items())
here := string(before) != string(after)
for _, k := range keys {
here = here || v.Applies(k)
}
verb := map[bool]string{false: "registered", true: "unregistered"}[unregister]
answer := map[string]any{verb: it.Kind + " " + it.Name, "keys": keys}
@@ -835,15 +842,15 @@ func Register(p Paths, it Item, nodes []string, unregister bool, state ConfigSta
answer["offered as"] = "/" + Plugin + ":" + it.Name
}
}
if changed {
if here {
// Rendered whenever it applies here, so the answer says what this node wrote, whichever of the
// watch and this call took the change.
rendered, err := RenderNow(p, write)
answer["rendered here"] = rendered
if err != nil {
answer["not written here"] = err.Error() // kept on the bus all the same; the next render tries again
}
answer["sessions"] = "a new session takes it; a running one at /reload-plugins"
} else if v.Applies(keys[0]) || len(keys) > 1 {
answer["here"] = "already so"
} else {
answer["here"] = "not this node: each node it is for takes it from the bus"
}
@@ -455,3 +455,16 @@ func TestOneFileThatCannotBeWrittenDoesNotStopTheOthers(t *testing.T) {
t.Fatalf("the other files were not written: %v", w)
}
}
// The answer says what this node wrote even when its own watch took the change first.
func TestTheAnswerSaysWhatWasWrittenWhenTheWatchWasFirst(t *testing.T) {
p, w := node(t, "laptop")
state, view := memConfig{}, NewConfigView(p)
it := Item{Kind: KindCommand, Name: "c", Scope: ScopeHome, Files: one("c", "x")}
first := it
view.Take(it.Key("laptop"), "put", &first) // the watch, first
answer, err := Register(p, it, nil, false, state, view, writer(w))
if err != nil || answer["rendered here"] == nil || answer["here"] != nil {
t.Fatalf("%v %v", answer, err)
}
}