The YAML `watches:` seed was the last piece of forge state the config
file carried. Everything else about watches already lived in the
extension: the table (SQLite, runtime-managed), the HTTP routes
(`GET/POST/DELETE /v1/watches`), the chat tools, the poller that reads
the table fresh every pass. A static seed list on top meant two homes
for one fact — and the seed's own semantics (import-once, ignored
once the table has rows) had to be explained to every reader.
Now the config carries none of it:
- `ClawConfig.watches` is gone, with the `Watch` seed type and the
boot-time validation loop that guarded it. A config still carrying
`watches:` is refused at parse time — `deny_unknown_fields` turns
the retirement into a loud migration, not a silent no-op.
- `Watch` moved to `watch_store` (re-exported from the crate root),
where the row's vocabulary belongs; `validate_watch` keeps guarding
the one door every writer shares — the routes and the tools both
call it, so the moved validation tests test it there.
- `seed_from_config` and the daemon's seeding are gone; the operator
seeds once over HTTP or `watches add`, and the table stays true.
The one guarantee the seed carried that nothing else did — boot
refuses a tokenless watch — goes with it, deliberately: a tokenless
watch now fails at its first poll, loudly, like any other watch the
agent adds at runtime. Boot-time certainty was paying for config
state the daemon no longer owns.