feat(sdk): punktfunk-scripting — the managed script/plugin runner (M5)
apple / swift (push) Successful in 1m18s
apple / screenshots (push) Successful in 4m42s
ci / web (push) Successful in 56s
ci / docs-site (push) Successful in 49s
decky / build-publish (push) Successful in 18s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 12s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
ci / bench (push) Successful in 5m14s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 12s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 56s
arch / build-publish (push) Successful in 15m11s
android / android (push) Successful in 15m50s
deb / build-publish (push) Successful in 16m9s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 14m12s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 14m8s
ci / rust (push) Successful in 24m55s
docker / deploy-docs (push) Successful in 10s
apple / swift (push) Successful in 1m18s
apple / screenshots (push) Successful in 4m42s
ci / web (push) Successful in 56s
ci / docs-site (push) Successful in 49s
decky / build-publish (push) Successful in 18s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 12s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
ci / bench (push) Successful in 5m14s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 12s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 56s
arch / build-publish (push) Successful in 15m11s
android / android (push) Successful in 15m50s
deb / build-publish (push) Successful in 16m9s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 14m12s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 14m8s
ci / rust (push) Successful in 24m55s
docker / deploy-docs (push) Successful in 10s
The optional supervision layer (RFC §8): one service runs everything in <config_dir>/scripts/ plus installed punktfunk-plugin-* packages (<config_dir>/plugins/node_modules/), as Effect fibers. - Plugins (a definePlugin default export, either main shape) are SUPERVISED: a failure restarts them with capped exponential backoff (jittered, 1s→60s); a clean return completes them. The Effect shape runs under the PunktfunkHost layer; the async-fn shape gets a facade client whose close is scope-guaranteed. - Bare scripts are one-shot: importing them is the run, no restart (export a plugin to be supervised). - Shutdown is STRUCTURAL: SIGINT/SIGTERM interrupt the whole fiber tree, so Effect plugins' scoped finalizers run and clients close before exit — the systemctl-stop story, and the reason the Effect plugin shape exists at all. - The sshd rule applies to unit files (world-writable → refused loudly); cache-busted imports make restarts real; --list for inventory. 6 new bun tests (17 total green): discovery + refusal, both plugin shapes against a mock host, crash→restart with backoff, one-shot semantics, and finalizer-on-interrupt. Live-verified against a real host: a supervised watcher plugin received library.changed through the pinned tunnel, and SIGTERM shut the tree down structurally (exit 0). Deferred to the packaging follow-up (release.yml is in flight in a parallel session): the vendored-Bun deb/rpm/iss packages and the host-log-ring tee (needs a host ingest endpoint); console page rides the other console surfaces. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+38
-1
@@ -94,7 +94,44 @@ export default definePlugin({
|
||||
|
||||
In v1 a plugin is a script you run (see below); the managed runner package is a later step.
|
||||
|
||||
## Running as a service
|
||||
## The runner: `punktfunk-scripting`
|
||||
|
||||
Instead of one unit file per script, run everything under the managed runner — it discovers
|
||||
your units and supervises them:
|
||||
|
||||
```sh
|
||||
bun src/runner-cli.ts # runs <config_dir>/scripts/* + installed punktfunk-plugin-*
|
||||
bun src/runner-cli.ts --list # show what it found
|
||||
```
|
||||
|
||||
- **Plugins** (a `definePlugin` default export, from the scripts dir or a
|
||||
`punktfunk-plugin-*` package installed under `<config_dir>/plugins/`): supervised — a crash
|
||||
restarts them with capped exponential backoff; a clean return completes them.
|
||||
- **Bare scripts**: importing them is the run — one-shot, no restart (export a plugin to be
|
||||
supervised).
|
||||
- **Shutdown is structural**: SIGINT/SIGTERM interrupt every unit's fiber — Effect plugins'
|
||||
scoped finalizers run (release the preset, deregister cleanly) and facade clients close
|
||||
before the process exits. This is what makes `systemctl stop` clean.
|
||||
- The sshd rule applies: a group/world-writable unit file is refused loudly.
|
||||
|
||||
systemd user unit for the runner (`~/.config/systemd/user/punktfunk-scripting.service`):
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=punktfunk script/plugin runner
|
||||
After=punktfunk-host.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/bun /path/to/sdk/src/runner-cli.ts
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
# SIGTERM (the default KillSignal) triggers the runner's structured shutdown.
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
```
|
||||
|
||||
## Running a single script as a service
|
||||
|
||||
systemd user unit (`~/.config/systemd/user/punktfunk-myscript.service`):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user