- FillRegion: insert the whole batch in one transaction (store.CreatePlantings)
instead of one round-trip per plop, and refuse fills over maxFillPlops (5000)
so a max-sized bed with tiny spacing can't generate ~10^5 sequential writes.
Guards the computed radius is finite/positive and clamps the region to the
object's bounds before packing (bounds hexCenters).
- FillNamedRegion + FillRegion share a fillLoaded body, so the object is loaded
and authorized once (no double objectForRole).
- Region is now rect-only — dropped the speculative circle fields/branch that
NamedRegion never produced and hexCenters didn't pack (circles are post-v1).
- NamedRegion guards a nil object and no longer maps a blank name to "all"
(blank → ErrInvalidInput, matching the doc).
- ClearObject documents why it deliberately doesn't require plantable.
Tests: empty/nil region name → ErrInvalidInput; an oversized fill → ErrInvalidInput
(over the cap). Tagged demo tidied (checked errors, domain.RoleViewer, t.Helper).
GOWORK=off go build/vet/test ./internal/... green; tagged agent test green against
majordomo (go.mod stays majordomo-free).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01JdQpdYYsTgtkJBxbcpAszi
Bulk, natural-language-shaped service operations (ACL-enforced like every other
op, so agent tools inherit permissions for free):
- ops.go: Region + NamedRegion (nw/ne/sw/se corners, north/south/east/west and
top/bottom/left/right halves, "all"; -y is north in the local frame).
FillRegion hex-packs plops at 2×radius pitch (radius = #15's max(1.5·spacing,
15cm)) clipped to the region, skipping any candidate that would sit entirely
inside an existing active plop. ClearObject soft-removes all active plops in one
UPDATE. DescribeGarden returns a structured summary (dims, objects+version,
plantings with plant/effective-count/rough compass location).
- store/plantings.go: ListActivePlantingsForObject + ClearObjectPlantings.
Agent toolbox (internal/agent), deliberately isolated:
- doc.go (untagged) keeps the package in the default build; tools.go is behind
the `majordomo` build tag and NOT in go.mod, so `go build/test ./...` and the
server binary carry no majordomo/LLM deps. Built + tested locally against real
majordomo (go test -tags majordomo ./internal/agent/).
- NewToolbox(svc, actorID) exposes list_gardens, describe_garden, create_object,
move_object, place_planting, fill_region, clear_object as llm.DefineTool
wrappers — thin typed adapters over the service, each running as the bound
actor.
Tests: NamedRegion for all names + unknown→ErrInvalidInput; deterministic
hex-packing count (60×60 bed → 4 plops) + re-fill skips covered; rotated bed
fills the correct LOCAL corner; ClearObject; viewer→ErrForbidden on fill/clear
but can describe; and the DESIGN corner/half scenario (garlic NE, basil NW, beans
south) verified via DescribeGarden. A tagged demo drives the same scenario
through the toolbox (JSON args → tool → service) and confirms a viewer is refused.
GOWORK=off go build/vet/test ./internal/... green (majordomo-free).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01JdQpdYYsTgtkJBxbcpAszi