T-IIZZ-notify-config-for-desktop-ntfy-webhook-channels-and-the-9
State: closed/done · Impact: medium · Complexity: large
notify: config declares channels (desktop, ntfy HTTP topic, webhook
for Slack or Discord) and events: pr.needs_response, pr.ci_failed,
task.parked, stage.ceiling_reached, phase.ready_for_review,
lease.expired, session.ended, hook.blocked,
orchestrator.dead_stop.
Approach
Section titled “Approach”- Define the
notify:config schema: namedchannels(a discriminated union ontype:desktop,ntfywithtopic_url,webhookwithurl+formatslack/discord/raw) and aneventsmap keyed by exactly the 9 canonical event names, each an array of channel names. - Retire
orchestrator.notify(Phase 2’s slice,lib/config/load.ts) outright — hard cutover, no compat shim — now that the top-levelnotify:section it said it would “absorb” is real. - Meta-define every top-level key per the P5 pattern (
category: 'automation',consumers,layers,applies_via,runs_in), covered by the existing meta completeness test. - Regenerate the generated docs (
sdlc docs generate) and the built plugin packs (agent-pants build) soconventions/sdlc-yaml.mdand the three.claude-plugin//.agents//.cursor-plugin/trees reflect the new section. - Grow
lib/services/notify/dispatch.ts’snotify()into channel-routing (events[event]-> channel names ->channels, best-effort per channel) and addlib/services/notify/webhook.ts(mirrorsntfy.ts: injectablefetchFn, POSTs a body shaped byformat). Landed here rather than inT-2QGZso that task’s call-site rewiring and new CLI ops have a real runtime to build on from the start, instead of both tasks touchingdispatch.tsin sequence.
| Area | Note |
|---|---|
solutions/ontological/lib/config/load.ts | notify: schema; retire orchestrator.notify |
solutions/ontological/lib/config/meta.ts | meta categories (unchanged; notify already listed under automation) |
solutions/ontological/lib/services/notify/dispatch.ts | channel-routing notify(), sendToChannel |
solutions/ontological/lib/services/notify/webhook.ts | new channel sender |
solutions/ontological/conventions/sdlc-yaml.md + built plugin packs | regenerated, not hand-edited |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
notify:validateschannels(desktop/ntfy/webhook, each shaped per its type) and aneventsmap whose keys are exactlypr.needs_response,pr.ci_failed,task.parked,stage.ceiling_reached,phase.ready_for_review,lease.expired,session.ended,hook.blocked,orchestrator.dead_stop— an unknown event key is a schema error (.strict()), and every top-level key carries.meta()(meta.test.tsstays green). - AC-2: An
events.*entry naming a channel absent fromchannelsfails config validation with an error naming the bad channel — caught atsdlc.yamlload time, not at notify-dispatch time. - AC-3:
orchestrator.notifyno longer exists in the schema (hard cutover); no code or test references it after this task. - AC-4:
bun run solutions/ontological/cli/sdlc.ts docs generate --checkandcargo run -q -p agent-pants -- check --config solutions/ontological/agent-pants.yamlare clean against the regeneratednotify:reference section.
Out of scope
Section titled “Out of scope”- The
notify send/notify testCLI ops, every Phase-2 call-site rewire (work.ts,hooks/run.ts,_pr_action.ts,prs.ts,merges.ts), and the two new detector wirings (lease.expired,session.ended):T-2QGZ. - Wiring
phase.ready_for_reviewandorchestrator.dead_stopto a real detector: no such detection code exists on this branch yet (seeT-2QGZ’s Out of scope for why these two stay config-only for now).
Dependencies
Section titled “Dependencies”- none