skillscript-runtime 0.18.9 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +1 -1
  2. package/dist/bootstrap.d.ts.map +1 -1
  3. package/dist/bootstrap.js +11 -3
  4. package/dist/bootstrap.js.map +1 -1
  5. package/dist/cli.js +13 -0
  6. package/dist/cli.js.map +1 -1
  7. package/dist/connectors/agent.d.ts +6 -2
  8. package/dist/connectors/agent.d.ts.map +1 -1
  9. package/dist/connectors/types.d.ts +2 -8
  10. package/dist/connectors/types.d.ts.map +1 -1
  11. package/dist/connectors/types.js.map +1 -1
  12. package/dist/dashboard/server.d.ts +49 -0
  13. package/dist/dashboard/server.d.ts.map +1 -1
  14. package/dist/dashboard/server.js +108 -0
  15. package/dist/dashboard/server.js.map +1 -1
  16. package/dist/errors.d.ts +25 -0
  17. package/dist/errors.d.ts.map +1 -1
  18. package/dist/errors.js +42 -0
  19. package/dist/errors.js.map +1 -1
  20. package/dist/mcp-server.js +3 -3
  21. package/dist/mcp-server.js.map +1 -1
  22. package/dist/parser.d.ts +1 -1
  23. package/dist/parser.d.ts.map +1 -1
  24. package/dist/parser.js +4 -4
  25. package/dist/parser.js.map +1 -1
  26. package/dist/runtime.d.ts +10 -0
  27. package/dist/runtime.d.ts.map +1 -1
  28. package/dist/runtime.js +1 -1
  29. package/dist/runtime.js.map +1 -1
  30. package/dist/scheduler.d.ts +54 -11
  31. package/dist/scheduler.d.ts.map +1 -1
  32. package/dist/scheduler.js +103 -33
  33. package/dist/scheduler.js.map +1 -1
  34. package/dist/skill-catalog.js +7 -11
  35. package/dist/skill-catalog.js.map +1 -1
  36. package/dist/trace.d.ts +9 -1
  37. package/dist/trace.d.ts.map +1 -1
  38. package/dist/trace.js +10 -2
  39. package/dist/trace.js.map +1 -1
  40. package/docs/adopter-playbook.md +98 -0
  41. package/docs/configuration.md +2 -0
  42. package/examples/skillscripts/hello-world.skill.provenance.json +1 -1
  43. package/package.json +1 -1
  44. package/scaffold/.env.example +22 -1
@@ -370,6 +370,104 @@ Per-skill capability declaration: skills declare what shell binaries they need i
370
370
 
371
371
  The operator policy validates `declared ∩ allowlist` — each skill's shell footprint becomes self-documenting and auditable. Slated for a future ring once the chokepoint + observability surfaces ship.
372
372
 
373
+ ## Trigger model (v0.19.0 — BREAKING)
374
+
375
+ **v0.19.0 collapses the trigger surface to two primitives.** Per the Scott + Perry decision (memory `ceaf4579`):
376
+
377
+ | Primitive | Purpose |
378
+ |---|---|
379
+ | `cron` | Time-based fires (unchanged) |
380
+ | `event` | Generic external-signal fires via HTTP POST to `/event` |
381
+
382
+ The previous sources (`session`, `agent-event`, `file-watch`, `sensor`) are **removed**. They were either parse-only stubs that never fired or substrate-coupled concepts that belong outside the runtime. Anything external becomes an adapter that POSTs to `/event` — including what would have been a session/agent-event/file-watch/sensor trigger. The `DeliveryMeta.origin.trigger_kind` receiver enum also drops `"session"` in lockstep (pre-v1.0 cleanup; the value was never functionally emitted).
383
+
384
+ ### The `event` primitive
385
+
386
+ Skills declare an event trigger in their frontmatter:
387
+
388
+ ```
389
+ # Skill: prox-handler
390
+ # Status: Approved
391
+ # Triggers: event: prox
392
+ # Vars: ROOM, USER
393
+
394
+ t:
395
+ emit(text="${USER} entered ${ROOM}")
396
+ default: t
397
+ ```
398
+
399
+ External services drive the skill by POSTing:
400
+
401
+ ```
402
+ POST /event HTTP/1.1
403
+ Host: localhost:7878
404
+ Content-Type: application/json
405
+ Authorization: Bearer <token> # if SKILLSCRIPT_EVENT_INGRESS_AUTH_TOKEN set
406
+
407
+ {
408
+ "event_name": "prox",
409
+ "params": { "ROOM": "kitchen", "USER": "scott" }
410
+ }
411
+ ```
412
+
413
+ Response on accept:
414
+
415
+ ```json
416
+ { "run_id": "f4a8b21c-...", "durability": "in-process" }
417
+ ```
418
+
419
+ The `run_id` is the runtime's `trace_id` — adopters paste it into the dashboard `/fires` view or query via the `fires({trace_id})` MCP tool to look up completion status.
420
+
421
+ ### Wire contract
422
+
423
+ | HTTP status | Meaning |
424
+ |---|---|
425
+ | **200** | Accepted into THIS process's in-memory queue. `{run_id, durability: "in-process"}`. Skill fires async; the 200 does NOT mean skill-completed |
426
+ | **400** | Body not JSON; or `event_name` missing/empty; or params don't match declared (missing required or unknown extras) |
427
+ | **401** | Auth token configured + missing/wrong `Authorization: Bearer <token>` |
428
+ | **404** | `/event` route not enabled OR `event_name` not registered |
429
+ | **405** | Wrong method (POST-only) |
430
+
431
+ **Param validation is strict v1**: every declared param must be present; no unknown params accepted. No defaults; no type coercion. JSON already carries types, and a type mismatch fails inside the consuming op with a real error. Defaults + types may land in v2 if real adopter need surfaces.
432
+
433
+ ### `event_name` semantics
434
+
435
+ - **Public contract** addressed by POSTers. Skill behind the event can swap without breaking callers — the `skill_name` is private impl.
436
+ - **Case-insensitive** at register + lookup (normalized to lowercase internally).
437
+ - **1:1**: one `event_name` → exactly one skill in the deployment. Fan-out is NOT supported — a skill can call other skills via `$ execute_skill` if needed.
438
+ - **Cross-skill rebind allowed but audited**: registering an `event_name` that's already bound to a different skill replaces the binding (last-write-wins) AND logs a visible line (`event_name 'X' rebound: skill A → skill B`). Prevents silent cross-skill hijack without blocking the declarative re-save path. Same skill re-registering its own event is a silent upsert.
439
+
440
+ ### Enabling the `/event` HTTP ingress
441
+
442
+ Off by default. Two operator knobs:
443
+
444
+ ```bash
445
+ # Required to open the /event route
446
+ SKILLSCRIPT_EVENT_INGRESS_ENABLED=true
447
+
448
+ # Optional bearer-token auth (when set, required on every POST /event)
449
+ SKILLSCRIPT_EVENT_INGRESS_AUTH_TOKEN=<token>
450
+ ```
451
+
452
+ When `eventIngressEnabled=true`, the route mounts on the same HTTP server as the dashboard/RPC (no second port). Default bind is `127.0.0.1` (localhost-only) — adopters wanting `0.0.0.0` external reach pass `--host 0.0.0.0` explicitly. Per Perry's framing: "enforce the DMZ assumption by the bind, not by hope."
453
+
454
+ ### Durability honesty
455
+
456
+ **`200 = ACCEPTED, not durable**.** The skill is queued in this process's memory; if the process crashes or restarts before the queue drains, the fire is lost. The `durability: "in-process"` field on every successful response self-describes this — adopters reading the response know the contract without consulting docs. Cron triggers have the same property today (no catch-up replay if the process was down).
457
+
458
+ Durable / at-least-once delivery is a v2 if real adopter need surfaces. Don't oversell the 200 contract; build durable queueing on top yourself if you need it now.
459
+
460
+ ### Migration from removed sources
461
+
462
+ If you have pre-v0.19.0 skills with `# Triggers: session: start` / `agent-event: X` / `file-watch: /path` / `sensor: X` declarations:
463
+
464
+ - **session start/end** → boot/shutdown lifecycle moved to the substrate (NanoClaw / your harness). If you need a runtime skill to fire at session-start, your harness POSTs to `/event` after boot.
465
+ - **agent-event** → external bridge (your agent fires `POST /event` when relevant).
466
+ - **file-watch** → external watcher script (inotify / chokidar / fswatch) POSTs to `/event`. The "how to call /event" pattern lives in the language reference call-example; the file-watching itself is standard OS plumbing — you own that script.
467
+ - **sensor** → same pattern as file-watch; sensor adapter POSTs to `/event`.
468
+
469
+ Skills declaring removed sources fail to parse on v0.19.0 (tier-1 parse error). Run `skillfile lint` against your corpus pre-upgrade to find them.
470
+
373
471
  ## Wiring the AgentConnector
374
472
 
375
473
  `AgentConnector` is the substrate-neutral delivery surface for `# Output: agent: X` / `# Output: template: X` lifecycle hooks and `notify()` / `exchange()` ops. The runtime calls into the contract; your impl decides where the payload lands (webhook, tmux session, file drop, IPC pipe, Slack thread, your own agent harness, etc.).
@@ -57,6 +57,8 @@ The CLI auto-loads `$SKILLSCRIPT_HOME/.env` at startup and populates `process.en
57
57
  | `SKILLSCRIPT_POLL_INTERVAL_SECONDS=30` | Scheduler tick / poll interval (seconds) | env > config > default `30` |
58
58
  | `SKILLSCRIPT_ABSOLUTE_TIMEOUT_MS=300000` | Runtime fallback timeout (ms) when no per-op / skill / connector default applies | env > config > default `300000` (5 min) |
59
59
  | `SKILLSCRIPT_MAX_RECURSION_DEPTH=10` | Composition recursion depth ceiling for `$ execute_skill` chains | env > config > default `10` |
60
+ | `SKILLSCRIPT_EVENT_INGRESS_ENABLED=true` | Mount `POST /event` for v0.19.0 event-triggered skills. Default `false` — route returns 404 when not enabled. Shares `SKILLSCRIPT_PORT` with dashboard/RPC (one HTTP server). | env > default `false` |
61
+ | `SKILLSCRIPT_EVENT_INGRESS_AUTH_TOKEN=<token>` | Bearer-token auth for `POST /event`. When set, every event POST requires `Authorization: Bearer <token>`; 401 otherwise. Default unset = open-internally (still gated by bind address). | env > default unset |
60
62
  | `OLLAMA_BASE_URL=http://...` | Ollama endpoint for LocalModel (default `http://localhost:11434`) | env > built-in default |
61
63
 
62
64
  `SKILLSCRIPT_HOME` is the chicken-and-egg case — the path to `.env` requires it, so `.env` can't set it. Use shell, Docker `-e`, or systemd `Environment=` instead.
@@ -2,7 +2,7 @@
2
2
  "provenance_version": "1.0",
3
3
  "language_version": "1.0",
4
4
  "compiler_version": "0.1.0-dev",
5
- "compiled_at": "2026-06-07T11:45:30.911Z",
5
+ "compiled_at": "2026-06-07T21:50:04.797Z",
6
6
  "source_skill": {
7
7
  "name": "hello-world"
8
8
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillscript-runtime",
3
- "version": "0.18.9",
3
+ "version": "0.19.0",
4
4
  "description": "Runtime, compiler, lint, CLI, and dashboard for Skillscript — a small declarative language for authoring agent workflows.",
5
5
  "license": "MIT",
6
6
  "author": "Scott Shwarts <scotts@pobox.com>",
@@ -64,10 +64,31 @@
64
64
  # reach the listener.
65
65
  # SKILLSCRIPT_HOST=0.0.0.0
66
66
 
67
- # Dashboard / serve HTTP port. Default 7878.
67
+ # Dashboard / serve HTTP port. Default 7878. Used for the SPA, JSON-RPC
68
+ # at /rpc, AND the v0.19.0 event-trigger ingress at /event (they share
69
+ # one HTTP server — no separate event port).
68
70
  # SKILLSCRIPT_PORT=8080
69
71
 
70
72
 
73
+ # ─── Event-trigger HTTP ingress (v0.19.0) ──────────────────────────────
74
+
75
+ # Enable POST /event for external HTTP-triggered skills. Default false —
76
+ # the route returns 404 when not enabled. Once enabled, external services
77
+ # POST {event_name, params} and the runtime fires the registered skill
78
+ # asynchronously, returning 200 + {run_id, durability: "in-process"}.
79
+ # The route mounts on SKILLSCRIPT_PORT (above); no separate port.
80
+ # Localhost-only by default — set SKILLSCRIPT_HOST=0.0.0.0 to expose
81
+ # beyond loopback. "Enforce the DMZ assumption by the bind, not by hope."
82
+ # SKILLSCRIPT_EVENT_INGRESS_ENABLED=true
83
+
84
+ # Optional bearer-token auth for POST /event. When set, every event
85
+ # POST must carry `Authorization: Bearer <token>` matching this value;
86
+ # 401 otherwise. Default unset = open-internally (still gated by the
87
+ # bind address). Cheap to wire early — turning it on later is just an
88
+ # env edit + restart, no refactor.
89
+ # SKILLSCRIPT_EVENT_INGRESS_AUTH_TOKEN=your-secret-token-here
90
+
91
+
71
92
  # ─── Runtime tuning ────────────────────────────────────────────────────
72
93
 
73
94
  # Scheduler tick / poll interval in seconds. Default 30. Lower (e.g. 5)