wicked-bus 2.2.1 → 2.2.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wicked-bus",
3
- "version": "2.2.1",
3
+ "version": "2.2.2",
4
4
  "description": "Lightweight, local-first SQLite event bus for AI agents and developer tools",
5
5
  "type": "module",
6
6
  "exports": {
@@ -150,3 +150,105 @@ into event_type forces subscribers to enumerate every producer.
150
150
  **Why subdomain is a column (not in event_type):**
151
151
  `wicked.phase.started` is semantic. Whether it's `crew.phase` or `deploy.phase`
152
152
  is identity, not semantics. Columns enable index-based filtering.
153
+
154
+ ## Worked example: lifecycle & gate events
155
+
156
+ > **This is an illustrative pattern, not a mandate.** wicked-bus does not ship,
157
+ > register, or enforce a lifecycle catalog — skills teach conventions, they do
158
+ > **not** hardcode other plugins' event catalogs. Treat the names below as an
159
+ > example that a multi-stage pipeline tool **MAY** adopt to stay consistent with the
160
+ > `wicked.<noun>.<past-tense-verb>` convention. Pick the nouns/verbs that fit
161
+ > your domain; nothing here is reserved.
162
+
163
+ Many ecosystem tools run a **staged, gated pipeline** — an engine that moves work
164
+ through ordered stages, with governance gates between them (for example a
165
+ migration pipeline with stages like *discover → knowledge-base → spec → plan →
166
+ transform → validate → deliver/cutover*, each guarded by an approval gate). Such a
167
+ tool needs a consistent way to signal "a stage was entered/completed" and "a gate
168
+ cleared/blocked" so other tools can observe progress.
169
+
170
+ Here is one internally-consistent way to name those events under the existing
171
+ convention.
172
+
173
+ ### Suggested event types
174
+
175
+ | Event type | Emitted when | Notes |
176
+ |------------|--------------|-------|
177
+ | `wicked.stage.entered` | A pipeline stage begins | noun=`stage`, verb=`entered` |
178
+ | `wicked.stage.completed` | A stage finishes successfully | mirror of `entered` |
179
+ | `wicked.gate.cleared` | A governance gate passes | the "go" signal |
180
+ | `wicked.gate.blocked` | A gate fails / withholds approval | the "stop" signal |
181
+ | `wicked.pipeline.completed` | The whole pipeline reaches its terminal milestone (e.g. delivery/cutover) | terminal milestone — stage carried in `subdomain` |
182
+
183
+ All five satisfy the rules: `wicked.` prefix, three segments, past-tense verb,
184
+ no domain or subdomain baked in. They are **semantic** — any pipeline engine
185
+ emitting "a stage was entered" shares `wicked.stage.entered`, regardless of which
186
+ tool it is.
187
+
188
+ ### Suggested domain & subdomain
189
+
190
+ - **`domain`** = the engine/orchestrator's identity (its package or tool name),
191
+ e.g. `domain = "engine"` (or `migration-factory`, `anti-legacy`, …). One domain
192
+ per engine — don't subdivide here.
193
+ - **`subdomain`** = `lifecycle.<stage>` — the functional area plus the specific
194
+ stage the event concerns, e.g. `lifecycle.transform`, `lifecycle.validate`,
195
+ `lifecycle.cutover`. *Which* stage is identity, not semantics, so it belongs in
196
+ the column, never in the event_type.
197
+
198
+ ### How a multi-stage pipeline names its transitions
199
+
200
+ A 7-stage pipeline does **not** invent a new event_type per stage. It reuses the
201
+ five semantic types above and distinguishes the stage via `subdomain`:
202
+
203
+ ```javascript
204
+ import { emit } from 'wicked-bus';
205
+
206
+ // Entering the "transform" stage
207
+ emit(db, config, {
208
+ event_type: 'wicked.stage.entered',
209
+ domain: 'engine',
210
+ subdomain: 'lifecycle.transform',
211
+ payload: { stage: 'transform', stage_number: 5, ref: '<authoritative-state-id>' },
212
+ });
213
+
214
+ // The gate guarding the transform→validate transition clears
215
+ emit(db, config, {
216
+ event_type: 'wicked.gate.cleared',
217
+ domain: 'engine',
218
+ subdomain: 'lifecycle.transform',
219
+ payload: { gate: 'transform', approver: 'architect', spec_version: '3.2.0' },
220
+ });
221
+
222
+ // A later gate withholds approval
223
+ emit(db, config, {
224
+ event_type: 'wicked.gate.blocked',
225
+ domain: 'engine',
226
+ subdomain: 'lifecycle.validate',
227
+ payload: { gate: 'validate', reason: 'acceptance criteria not green' },
228
+ });
229
+ ```
230
+
231
+ ### Why this shape filters well
232
+
233
+ Because the stage lives in `subdomain` and the engine in `domain`, subscribers
234
+ get expressive filters for free:
235
+
236
+ ```bash
237
+ # Every gate outcome from any engine, any stage
238
+ wicked-bus subscribe --filter 'wicked.gate.*'
239
+
240
+ # Every stage transition from any engine, any stage
241
+ wicked-bus subscribe --filter 'wicked.stage.*'
242
+
243
+ # Everything a specific engine emits across its whole lifecycle
244
+ wicked-bus subscribe --filter '*@engine'
245
+ ```
246
+
247
+ ### The bus is transport, not the system of record
248
+
249
+ These events **announce** transitions; they do not **store** lifecycle state. The
250
+ bus is fire-and-forget transport and TTL-sweeps payloads — authoritative lifecycle
251
+ state (which stage you're in, who signed which gate) lives in the pipeline tool's
252
+ own durable store (its spec headers, DB, or audit log), not on the bus. Put a
253
+ reference (an id) in the payload and resolve details from the system of record;
254
+ never treat a polled event as the source of truth for current state.