Commit Graph
9 Commits
Author SHA1 Message Date
vhaudiquet b70a56c325 refactor(calendar): move the reminder source beside the feeds
CalendarWatch, the client resolution, and the slot policy were all
feed domain living in the claw's config and source tree; only the
extension adapter was the claw's. The reminder source now ships in
the integration as the default answer to "what does a start time
mean": one slot per lead time, calendar:<name> keys, fed to the
consumer's dispatcher. The crate doc drops its no-policy claim to
match, and the claw's resident prefixes take the calendar prefix
from the integration so the spelling cannot drift.
2026-10-20 05:53:43 +02:00
vhaudiquet fc0cbbcb6b refactor(forge): classify account notifications beside the vocabulary
The triage mapped the forges' notification reasons onto the claw's
verdicts, but it co-evolves with the vocabulary, not with the claw:
a reason that enters it (Gitea's collapsed shape) needs a verdict in
the same change, and its tests pin the mapping against the
vocabulary's own types. It now lives in the integration crate as the
default classification; a consumer may reclassify on top. The claw
imports it like the rest of the forge seam.
2026-10-20 05:49:14 +02:00
vhaudiquet 5fdd17b901 refactor(claw): assemble the daemon from an extension set
The daemon named every feature twice: once in the interactive
handler's sixteen-argument constructor, once across the source list,
the tick, and the boot pass. Both assemblies are now loops over one
ClawExtension trait, so an integration is a struct plus a line in
the standard set. The chain order, the detect order, and the boot
order are unchanged; the surface suite pins them. Each extension
struct is the boundary a later move into the integration crates
would lift wholesale.
2026-10-20 05:39:57 +02:00
vhaudiquet 8ab513d49f fix(claw): list the subagents manifest in the claw image
rhema-code grew a path dependency on the new rhema-subagents crate, but
the image's manifest-only staging layer never copied its Cargo.toml, so
workspace resolution died before cargo fetch could run.
2026-10-19 23:14:31 +02:00
vhaudiquet cb30ba9469 style(claw): rustfmt the watch-credential change
The credential-resolution commit landed with two violations this
editor's format-on-save caught — an unsorted import in the handler and
wrapping in the daemon and source — reformatted here so the tree is
cargo-fmt clean.
2026-10-19 20:14:07 +02:00
vhaudiquet 1cdc2e8648 feat(claw): derive a blank watch credential from the matching account
A repo watch row carries no account link: its only credentials were the
token stored on the row and the forge's environment variable, so a
watch added without either polled — and replied — anonymously. Against
a private repository that is a 404 on every pass, and nothing ever
lands: no dispatch, no reply, only a per-pass warning in the logs.

The watch credential now resolves in three tiers: the row's token,
then the env var, then the token-kind account identity of the same
forge — instance-scoped on a self-hosted forge (the gitea watch of
git.example borrows the gitea account saved with that base URL). A
password-kind account is skipped, never borrowed. ForgeSource and the
ClawHandler resolve through the same chain and key their client caches
on the resolved value, so the reply authenticates as the identity the
poll did — and a rotation or a later-saved account is a new client on
the next pass, no restart.
2026-10-19 19:44:39 +02:00
vhaudiquet 7c707e7a09 feat(claw): list account watches beside repo watches on the surface
A saved account whose forge notifications are not actually followed was
invisible: the save's watch flag defaults to false on the tool and the
HTTP route, and GET /v1/watches listed only the repo-watch table. The
first question a silent forge thread raises — is my account even
subscribed? — was unanswerable from outside. The route now answers it.
2026-10-19 19:40:59 +02:00
vhaudiquet 04549a7df5 fix(claw): dispatch reason-less forge notifications to the thread's agent
Gitea's notifications feed names no per-row reason, so the adapter
collapses every row under one fixed NotificationReason::Other spelling
— and the claw's triage mapped every Other to Surface: the notification
reached the device queue and never a dispatch. A comment on a thread
the account authored could therefore never wake the agent on a
reason-less forge, whatever the watches said.

The adapter now publishes that spelling as gitea::COLLAPSED_REASON —
it is the seam's contract, not a detail — and the triage treats it as
the known shape it is: a notification on a thread of the account's own
dispatches the implementer. A spelling no adapter owns still surfaces;
an unknown shape remains the user's to judge, never the agent's to
guess at.
2026-10-19 19:40:44 +02:00
vhaudiquet 81da26b955 feat(rhema-code): add the colors setting with four palettes
The stored `colors` key names a palette — rhema (the default,
Jadeite), aquamarine, black-and-white, or dracula — and the
Appearance page of /settings cycles it live, like the theme and
icon toggles beside it. Each palette carries a dark and a light
appearance under the existing `theme` key; dracula's light side is
derived, the official palette ships only dark.

The appearance decision moves off token comparison: Theme now
answers is_dark() from the ground/text luminance, so palettes
beyond the original two get the right per-profile fallback tones.
2026-10-17 04:28:31 +08:00