@fusion/plugin-sdk's package.json points its import entry at
src/index.ts (TS source), and that file imports core/src/plugin-types.js
via relative path. Node 22 ESM has no TS loader so the chain
unraveled at runtime: the plugin loader successfully resolved our
compiled dist/index.js, but the very first `import { definePlugin }
from "@fusion/plugin-sdk"` walked into TS source and fell over.
definePlugin is a pure typed identity function — it adds no runtime
behavior. Inline its source plus a structural copy of the plugin
context/route/manifest types we use, drop the @fusion/plugin-sdk
dependency entirely. The compiled output now imports nothing outside
node:crypto and Node builtins, so it can load anywhere fusion can
spawn ESM modules.
When fusion publishes a compiled SDK build, swap the inline types
back to import statements and restore the workspace dependency.
The runtime plugin packages (paperclip, hermes, openclaw) all build to
dist/ and have package.json exports import pointing at dist/index.js.
Fusion's plugin loader uses Node ESM dynamic import on the absolute
installation path, which fails on TypeScript source because there's
no TS loader at runtime. Drop noEmit, exclude tests from compilation,
emit dist + sourcemaps + d.ts so the loader can resolve dist/index.js
the same way it resolves paperclip's.
Plugin should be re-registered with path
/app/plugins/fusion-plugin-telemetry-watcher/dist/index.js after the
fusion redeploy lands the new dist artifact.
New workspace package fusion-plugin-telemetry-watcher that turns a
Grafana Alerting webhook payload into a Fusion incident task in the
triage column. Hooks the dedup/severity/rate-limit primitives that
PostHog/Sentry/Slack sources will reuse in Phase 2.
Pipeline:
POST /api/plugins/fusion-plugin-telemetry-watcher/grafana-webhook
→ bearer-secret check
→ parseGrafanaPayload (one signal per firing alert; resolved alerts
are dropped — recovery is verified post-deploy by the QA agent)
→ classifySeverity P0/P1/P2/P3 with critical-path keyword
escalation (payment/auth/billing/subscription)
→ DedupCache 4h fingerprint window — repeat fires log against the
existing task instead of opening duplicates
→ IncidentRateLimiter 5/h, 20/d — overflow becomes a "telemetry
storm" mega-task in a future phase
→ taskStore.createTask({ column: "triage", priority })
→ optional auto-assign to Triage Agent
14 unit tests cover severity buckets, critical-path escalation, dedup
windowing/eviction, hourly+daily rate caps, and the Grafana payload
parser (firing vs resolved, label-based domain inference).
Settings expose all thresholds + secret + dedup window + rate limits
through the dashboard plugin settings UI. README documents the deploy
+ register + Grafana contact-point wiring.