Address #132 review: one verb list, self-reporting tools, rune-safe log
Build image / build-and-push (push) Successful in 8s
Build image / build-and-push (push) Successful in 8s
- changeClaim is built from one changeVerbs list; the opener is just done/fixed/undone so an informational "Updated totals:" can't trip it. - public_link (get reads) and undo_change (nothing left to revert) are self-reporting: their success no longer counts as a change by name; the adapter says whether they changed something (noteChange / didChange). - whenMissing covers the object and plant tools too (move/update/delete object, clear/remove plantings by object, update/delete plant). - The step summary cuts on a rune boundary. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
+32
-7
@@ -277,6 +277,10 @@ type adapter struct {
|
||||
today string
|
||||
|
||||
mu sync.Mutex
|
||||
// changed is set by the tools whose success does not itself mean a change
|
||||
// — public_link (get reads) and undo_change (nothing left to revert) — when
|
||||
// they did change something, for Run's honesty check.
|
||||
changed bool
|
||||
// reverts is every change set undo_change produced this turn. A revert is
|
||||
// its own change set (it points back at the one it undid, and the target is
|
||||
// marked undone), so it never joins the turn's scope — which leaves a turn
|
||||
@@ -285,6 +289,20 @@ type adapter struct {
|
||||
reverts []int64
|
||||
}
|
||||
|
||||
// noteChange records that a self-reporting tool changed something.
|
||||
func (a *adapter) noteChange() {
|
||||
a.mu.Lock()
|
||||
a.changed = true
|
||||
a.mu.Unlock()
|
||||
}
|
||||
|
||||
// didChange reports whether a self-reporting tool changed something this turn.
|
||||
func (a *adapter) didChange() bool {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
return a.changed
|
||||
}
|
||||
|
||||
// lastRevert is the newest change set undo_change produced this turn, if any.
|
||||
func (a *adapter) lastRevert() *int64 {
|
||||
a.mu.Lock()
|
||||
@@ -393,8 +411,9 @@ func (a *adapter) moveObject(ctx context.Context, args struct {
|
||||
YCM float64 `json:"yCm" description:"new center y in garden cm"`
|
||||
Version int64 `json:"version" description:"the object's current version (from describe_garden)"`
|
||||
}) (any, error) {
|
||||
return a.svc.UpdateObject(ctx, a.actor, args.ObjectID,
|
||||
o, err := a.svc.UpdateObject(ctx, a.actor, args.ObjectID,
|
||||
service.ObjectPatch{XCM: &args.XCM, YCM: &args.YCM}, args.Version)
|
||||
return o, whenMissing(err, "object", args.ObjectID, "describe_garden")
|
||||
}
|
||||
|
||||
func (a *adapter) placePlanting(ctx context.Context, args struct {
|
||||
@@ -510,11 +529,12 @@ func (a *adapter) updatePlant(ctx context.Context, args struct {
|
||||
Vendor *string `json:"vendor" description:"optional vendor name"`
|
||||
Notes *string `json:"notes" description:"optional free-text notes"`
|
||||
}) (any, error) {
|
||||
return a.svc.UpdatePlant(ctx, a.actor, args.PlantID, service.PlantPatch{
|
||||
p, err := a.svc.UpdatePlant(ctx, a.actor, args.PlantID, service.PlantPatch{
|
||||
Name: args.Name, Category: args.Category, SpacingCM: args.SpacingCM, Color: args.Color,
|
||||
SetDays: args.DaysToMaturity != nil, DaysToMaturity: args.DaysToMaturity,
|
||||
SourceURL: args.SourceURL, Vendor: args.Vendor, Notes: args.Notes,
|
||||
}, args.Version)
|
||||
return p, whenMissing(err, "plant of the user's own", args.PlantID, "find_plant")
|
||||
}
|
||||
|
||||
func (a *adapter) addJournalEntry(ctx context.Context, args struct {
|
||||
@@ -542,7 +562,7 @@ func (a *adapter) clearObject(ctx context.Context, args struct {
|
||||
}
|
||||
n, err := a.svc.ClearPlantings(ctx, a.actor, args.ObjectID, service.ClearOptions{RemovedAt: on})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, whenMissing(err, "object", args.ObjectID, "describe_garden")
|
||||
}
|
||||
return map[string]int{"cleared": n}, nil
|
||||
}
|
||||
@@ -563,7 +583,7 @@ func (a *adapter) removePlantings(ctx context.Context, args struct {
|
||||
n, err := a.svc.ClearPlantings(ctx, a.actor, args.ObjectID,
|
||||
service.ClearOptions{PlantID: &args.PlantID, RemovedAt: on})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, whenMissing(err, "object", args.ObjectID, "describe_garden")
|
||||
}
|
||||
return map[string]int{"removed": n}, nil
|
||||
}
|
||||
@@ -727,6 +747,7 @@ func (a *adapter) undoChange(ctx context.Context, args struct {
|
||||
}
|
||||
a.mu.Lock()
|
||||
a.reverts = append(a.reverts, cs.ID)
|
||||
a.changed = true
|
||||
a.mu.Unlock()
|
||||
return res, nil
|
||||
}
|
||||
@@ -795,17 +816,18 @@ func (a *adapter) updateObject(ctx context.Context, args struct {
|
||||
RotationDeg *float64 `json:"rotationDeg" description:"optional new rotation in degrees"`
|
||||
Plantable *bool `json:"plantable" description:"optional: whether the object can hold plants"`
|
||||
}) (any, error) {
|
||||
return a.svc.UpdateObject(ctx, a.actor, args.ObjectID, service.ObjectPatch{
|
||||
o, err := a.svc.UpdateObject(ctx, a.actor, args.ObjectID, service.ObjectPatch{
|
||||
Name: args.Name, WidthCM: args.WidthCM, HeightCM: args.HeightCM,
|
||||
RotationDeg: args.RotationDeg, Plantable: args.Plantable,
|
||||
}, args.Version)
|
||||
return o, whenMissing(err, "object", args.ObjectID, "describe_garden")
|
||||
}
|
||||
|
||||
func (a *adapter) deleteObject(ctx context.Context, args struct {
|
||||
ObjectID int64 `json:"objectId" description:"object to delete (with its plantings)"`
|
||||
}) (any, error) {
|
||||
if err := a.svc.DeleteObject(ctx, a.actor, args.ObjectID); err != nil {
|
||||
return nil, err
|
||||
return nil, whenMissing(err, "object", args.ObjectID, "describe_garden")
|
||||
}
|
||||
return map[string]any{"deleted": args.ObjectID}, nil
|
||||
}
|
||||
@@ -974,7 +996,7 @@ func (a *adapter) deletePlant(ctx context.Context, args struct {
|
||||
return nil, fmt.Errorf("%w: the plant is still used — by plantings (past seasons count) or a seed lot — so it stays; tell the user rather than removing those", domain.ErrPlantInUse)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, whenMissing(err, "plant of the user's own", args.PlantID, "find_plant")
|
||||
}
|
||||
return map[string]any{"deleted": args.PlantID}, nil
|
||||
}
|
||||
@@ -1164,5 +1186,8 @@ func (a *adapter) publicLink(ctx context.Context, args struct {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if action != "get" {
|
||||
a.noteChange()
|
||||
}
|
||||
return a.linkOf(link), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user