Address #122 review: pageable read_journal, service-clock removal
Build image / build-and-push (push) Successful in 20s

- read_journal now takes an offset, so the hasMore it returns is
  actionable — an agent can page a journal longer than 50 entries.
- remove_planting goes through a new service RemovePlanting that stamps
  removed_at from s.now() (the injectable clock ClearObject and the fill
  path use), instead of the adapter computing the date off the wall clock.
  It delegates to UpdatePlanting, so the role check, version guard and
  history record are unchanged. Drops the now-unused time import.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01H3zbym8Doka2d7D48maSgZ
This commit is contained in:
2026-07-22 21:39:20 -04:00
co-authored by Claude Opus 4.8
parent 887a3c2cc6
commit 7b150275ae
2 changed files with 17 additions and 7 deletions
+6 -7
View File
@@ -2,7 +2,6 @@ package agent
import (
"context"
"time"
"gitea.stevedudenhoeffer.com/steve/majordomo/llm"
@@ -218,8 +217,9 @@ func (a *adapter) readJournal(ctx context.Context, args struct {
ObjectID *int64 `json:"objectId" description:"optional bed to narrow to; omit for the whole garden"`
From string `json:"from" description:"optional earliest observed date, YYYY-MM-DD"`
To string `json:"to" description:"optional latest observed date, YYYY-MM-DD"`
Offset int `json:"offset" description:"how many entries to skip; pass the count you've already seen to page when hasMore is true"`
}) (any, error) {
q := service.JournalQuery{ObjectID: args.ObjectID, Limit: 50}
q := service.JournalQuery{ObjectID: args.ObjectID, Limit: 50, Offset: args.Offset}
if args.From != "" {
q.From = &args.From
}
@@ -230,6 +230,7 @@ func (a *adapter) readJournal(ctx context.Context, args struct {
if err != nil {
return nil, err
}
// hasMore is actionable now: re-call with offset += len(entries) to page.
return map[string]any{"entries": entries, "hasMore": hasMore}, nil
}
@@ -261,11 +262,9 @@ func (a *adapter) removePlanting(ctx context.Context, args struct {
PlantingID int64 `json:"plantingId" description:"plop to remove (its id from describe_garden)"`
Version int64 `json:"version" description:"the plop's current version (from describe_garden)"`
}) (any, error) {
// Soft-remove: set removed_at to today, mirroring clear_object, so the plop
// stays in the planting history and the change is undoable.
today := time.Now().UTC().Format("2006-01-02")
return a.svc.UpdatePlanting(ctx, a.actor, args.PlantingID,
service.PlantingPatch{SetRemovedAt: true, RemovedAt: &today}, args.Version)
// Soft-remove via the service, so removed_at is stamped from the same
// (injectable) clock clear_object uses rather than the adapter's wall clock.
return a.svc.RemovePlanting(ctx, a.actor, args.PlantingID, args.Version)
}
func (a *adapter) listSeedLots(ctx context.Context, args struct {