LiveSeeds
What the page's three seed tags carry — `#milpa-live-signals`, `#milpa-live-persist` and `#milpa-live-computed` — merged from the host's own and every view a section declared (greenhouse decisions/0211). The runtime reads ONE tag of each kind per page (`getElementById`), so the host is the only emitter and this is where the merge happens. Merging is by NAME and it is loud: the same signal declared twice with DIFFERENT values is a {@see SeedConflictException} naming the key and both declarers — never a silent last-one-wins, which would make one guest's seed depend on section order. The same name with the SAME value is not a conflict: two declarers agreeing is agreement, not a clash. `persist` is a list of names, so it merges by deduplication and can never conflict. Every declarer is named when it merges (`the panel`, `section «agent»`), which is what makes the conflict message actionable.
LiveSeeds::empty()
public static function empty(): selfNothing seeded — the three tags are still emitted, empty: one truth, never a missing tag.
LiveSeeds::of()
public static function of(string $source, array $signals = [], array $persist = [], array $computed = []): selfThe seeds one declarer brings, named.
Parameters
| Name | Type | Description |
|---|---|---|
| $source | string | who declares them — `the panel`, `section «agent»` |
| $signals | array<string, mixed> | |
| $persist | list<string> | |
| $computed | array<string, mixed> |
LiveSeeds::merge()
public function merge(self $other): selfThese seeds plus `$other`'s.
Parameters
| Name | Type | Description |
|---|---|---|
| $other | self |
Throws
SeedConflictException when both declare one name with different values
LiveSeeds::isEmpty()
public function isEmpty(): boolTrue when nothing was seeded at all.