What an inline routine sees
The triggering event is bound in scope as one normalised shape, whatever the signal type:
signal.id, signal.typeName, signal.subject, signal.occurredAtsignal.source.{ kind, id, label, url }signal.properties.<field> // type-specific fields — for a realm signal these are the event's // mapping keys (repo, number, author, …); read them from heretrigger // "signal" | "cron"now // ISO-8601 timestamp of this rundryRun // true when being tested — GUARD every external effect with if (!dryRun)A routine reacts through the typed gateway.* surface — read with gateway.kg.query, judge with gateway.ai.classify, act with Realm Functions or gateway.notifications.createNotification. Reads and gateway.ai.* are always safe; guard writes with if (!dryRun).
if (trigger !== "signal" || !signal) { console.log("not a signal event"); return; }const { repo, number, author } = signal.properties;const [owner, name] = String(repo).split("/");const commits = await gateway.gh.reposListCommits({ owner, repo: name, author, per_page: 1 });const isNew = commits.length === 0;console.log(isNew ? `new contributor ${author}` : `${author} has prior commits`);if (isNew) { console.log(dryRun ? `WOULD notify about PR #${number}` : `notifying about PR #${number}`); if (!dryRun) await gateway.notifications.createNotification({ event: "NewContributorPR", source: "pr-review", url: signal.source.url });}
