Skip to content

Commit 7777e8f

Browse files
os-zhuangclaude
andauthored
fix(spec)!: retire the never-built typed-event system; the lifecycle registry now lists the events that actually fire (#4241)
* fix(spec): retire the never-built typed-event system; registry now lists the events that actually fire The lifecycle-event surface promised a typed-event system that was never built, in three layers (#4212 leftovers, ADR-0049 enforce-or-remove): - kernel/plugin-lifecycle-events.zod.ts: 346 lines of payload schemas + a 21-name event enum — zero consumers for every export, and the enum both listed 17 names nothing fires and missed 10 events that DO fire. Deleted, with its test and barrel line; the 13 schemas leave json-schema.manifest.json and authorable-surface.json in the same PR (sanctioned deliberate-removal path; the keys were never authorable — they described runtime event payloads no config author can write, so the silent-strip class the ratchet guards against is vacuous here). - contracts/plugin-lifecycle-events.ts: IPluginLifecycleEvents kept the same 17 dead names alongside 5 real ones, plus an ITypedEventEmitter nothing implements. Rewritten as the registry of the 14 events with a real emitter — kernel:{ready,bootstrapped,listening,shutdown}, app:seeded, metadata:reloaded (metadata now optional, matching the documented contract), external.schema.drift, ai:routes (out-of-repo emitter, in-repo listener), auth:configure, and the {service}:ready convention family (mcp, automation, analytics, external-datasource, datasource-admin) — each with its payload as observed at the fire site. - Enforcement so the registry cannot rot again: LifecycleEventName now types IPluginContext.hook/trigger in @objectstack/core as LifecycleEventName | (string & {}) — known names autocomplete, custom cross-plugin names stay legal — and a pinning test asserts two-way equality between the interface keys and the fire-site inventory. Docs follow the code: the generated reference page for the deleted zod file is gone (nav + index links updated via gen:docs), PROTOCOL_MAP row repointed at the contracts registry, skill reference index regenerated. Verified: spec 7142 tests green (275 files), core 437 green, spec tsc --noEmit clean, and the full generated-artifact gate family in sync (docs 251, skill refs/docs/examples, api-surface, authorable-surface, spec-changes, upgrade-guide, exported-any). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HrRNgrWaRtggzmrHpbomyh * chore: changeset for the lifecycle-event registry retirement Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HrRNgrWaRtggzmrHpbomyh --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent d6938bf commit 7777e8f

18 files changed

Lines changed: 299 additions & 1164 deletions
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
"@objectstack/spec": major
3+
"@objectstack/core": patch
4+
---
5+
6+
fix(spec)!: retire the never-built typed-event system; the lifecycle registry now lists the events that actually fire (#4212 follow-up)
7+
8+
The lifecycle-event surface promised a typed-event system that was never
9+
built, in three layers. `kernel/plugin-lifecycle-events.zod.ts` shipped ten
10+
payload schemas (`PluginRegisteredEvent`, `PluginErrorEvent`,
11+
`HookTriggeredEvent`, `KernelReadyEvent`, …) and a 21-name
12+
`PluginLifecycleEventType` enum — zero consumers for every export, and the
13+
enum was wrong in both directions: 17 names nothing fires, 10 real events
14+
missing. `contracts/plugin-lifecycle-events.ts` declared the same 17 dead
15+
names in `IPluginLifecycleEvents` next to 5 real ones, plus an
16+
`ITypedEventEmitter` interface nothing implements. All of it read as a
17+
promise; anyone who coded against it (hooking `plugin:started`, awaiting
18+
`plugin:error`) registered a handler that could never fire, with no error
19+
saying so — the same silent-drop shape as the #4212 lifecycle-hook family.
20+
21+
Removed, with zero consumers verified repo-wide:
22+
23+
- `kernel/plugin-lifecycle-events.zod.ts` and every export: `EventPhase`,
24+
`PluginEventBase`, `PluginRegisteredEvent`, `PluginLifecyclePhaseEvent`,
25+
`PluginErrorEvent`, `ServiceRegisteredEvent`, `ServiceUnregisteredEvent`,
26+
`HookRegisteredEvent`, `HookTriggeredEvent`, `KernelEventBase`,
27+
`KernelReadyEvent`, `KernelShutdownEvent`, `PluginLifecycleEventType`
28+
(schemas and inferred types).
29+
- `ITypedEventEmitter` from `contracts/plugin-lifecycle-events.ts`.
30+
- The 17 never-fired names from `IPluginLifecycleEvents`.
31+
32+
`IPluginLifecycleEvents` is now the registry of the **14 events with a real
33+
emitter**`kernel:{ready,bootstrapped,listening,shutdown}`, `app:seeded`,
34+
`metadata:reloaded` (payload `metadata` now optional, matching the documented
35+
contract), `external.schema.drift`, `ai:routes`, `auth:configure`, and the
36+
`{service}:ready` convention family (`mcp`, `automation`, `analytics`,
37+
`external-datasource`, `datasource-admin`) — each payload as observed at its
38+
fire site. A new `LifecycleEventName` union types
39+
`PluginContext.hook`/`trigger` in `@objectstack/core` as
40+
`LifecycleEventName | (string & {})`: known names autocomplete, custom
41+
cross-plugin names stay legal, existing callers compile unchanged. A pinning
42+
test asserts two-way equality between the interface keys and the fire-site
43+
inventory.
44+
45+
FROM → TO:
46+
47+
- `PluginLifecycleEventType``LifecycleEventName` (the union of names that
48+
fire). There is no runtime enum; the bus is open by design.
49+
- Event payload schemas (`KernelReadyEvent`, `PluginErrorEvent`, …) → the
50+
payload tuples on `IPluginLifecycleEvents`. No wire format existed or
51+
exists; payloads are in-process arguments.
52+
- `ITypedEventEmitter``PluginContext.hook`/`trigger` (the emitter that
53+
actually exists).
54+
- Handlers for the 17 dead names → delete them; they never ran. For plugin
55+
phase observation use the boot report (ADR-0084); for per-plugin errors the
56+
kernel throws/logs at the failing phase.
57+
58+
Plain deletion rather than `retiredKey()` tombstones, per the #4233
59+
precedent: these keys were never authorable — they described runtime event
60+
payload records no config author can write, so the silent-strip class the
61+
authorable-surface ratchet guards against is vacuous. Its baseline entries
62+
and the `json-schema.manifest.json` keys are dropped deliberately in this PR.
63+
No ADR-0087 conversion: no stack metadata names these types; there is nothing
64+
for `os migrate meta` to rewrite.

content/docs/getting-started/quick-reference.mdx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ Plugin architecture, manifests, and kernel runtime.
6464
| **[Context](/docs/references/kernel/context)** | `context.zod.ts` | KernelContext | Runtime execution context |
6565
| **[Plugin](/docs/references/kernel/plugin)** | `plugin.zod.ts` | Plugin, PluginLifecycle | Plugin system interface |
6666
| **[Plugin Capability](/docs/references/kernel/plugin-capability)** | `plugin-capability.zod.ts` | PluginCapability | Plugin capability declarations |
67-
| **[Plugin Lifecycle](/docs/references/kernel/plugin-lifecycle-events)** | `plugin-lifecycle-events.zod.ts` | PluginEventBase, EventPhase | Plugin lifecycle events |
6867
| **[Plugin Lifecycle Advanced](/docs/references/kernel/plugin-lifecycle-advanced)** | `plugin-lifecycle-advanced.zod.ts` | AdvancedPluginLifecycleConfig, PluginHealthCheck | Advanced lifecycle hooks |
6968
| **[Plugin Loading](/docs/references/kernel/plugin-loading)** | `plugin-loading.zod.ts` | PluginLoadingConfig | Plugin loading and init |
7069
| **[Plugin Security](/docs/references/kernel/plugin-security-advanced)** | `plugin-security-advanced.zod.ts` | KernelSecurityPolicy, PluginPermission | Plugin sandboxing |

content/docs/references/index.mdx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ Defines the plugin architecture and kernel runtime.
115115
| `context.zod.ts` | `KernelContextSchema` | Kernel execution context with user, org, tenant info |
116116
| `plugin.zod.ts` | `PluginSchema` | Plugin lifecycle and interface definitions |
117117
| `plugin-capability.zod.ts` | `PluginCapabilitySchema` | Plugin capability declarations |
118-
| `plugin-lifecycle-events.zod.ts` | `PluginLifecycleEventsSchema` | Plugin lifecycle event definitions |
119118
| `plugin-lifecycle-advanced.zod.ts` | `PluginLifecycleAdvancedSchema` | Advanced lifecycle hooks |
120119
| `plugin-loading.zod.ts` | `PluginLoadingSchema` | Plugin loading and initialization |
121120
| `plugin-security-advanced.zod.ts` | `PluginSecurityAdvancedSchema` | Plugin security and sandboxing |

content/docs/references/kernel/index.mdx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ This section contains all protocol schemas for the kernel layer of ObjectStack.
2222
<Card href="/docs/references/kernel/plugin" title="Plugin" description="Source: packages/spec/src/kernel/plugin.zod.ts" />
2323
<Card href="/docs/references/kernel/plugin-capability" title="Plugin Capability" description="Source: packages/spec/src/kernel/plugin-capability.zod.ts" />
2424
<Card href="/docs/references/kernel/plugin-lifecycle-advanced" title="Plugin Lifecycle Advanced" description="Source: packages/spec/src/kernel/plugin-lifecycle-advanced.zod.ts" />
25-
<Card href="/docs/references/kernel/plugin-lifecycle-events" title="Plugin Lifecycle Events" description="Source: packages/spec/src/kernel/plugin-lifecycle-events.zod.ts" />
2625
<Card href="/docs/references/kernel/plugin-loading" title="Plugin Loading" description="Source: packages/spec/src/kernel/plugin-loading.zod.ts" />
2726
<Card href="/docs/references/kernel/plugin-registry" title="Plugin Registry" description="Source: packages/spec/src/kernel/plugin-registry.zod.ts" />
2827
<Card href="/docs/references/kernel/plugin-runtime" title="Plugin Runtime" description="Source: packages/spec/src/kernel/plugin-runtime.zod.ts" />

content/docs/references/kernel/meta.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"---Plugin Lifecycle---",
55
"plugin",
66
"plugin-lifecycle-advanced",
7-
"plugin-lifecycle-events",
87
"plugin-loading",
98
"plugin-registry",
109
"plugin-runtime",

content/docs/references/kernel/plugin-lifecycle-events.mdx

Lines changed: 0 additions & 220 deletions
This file was deleted.

packages/core/src/types.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
22

33
import { ObjectKernel } from './kernel.js';
4-
import type { Logger } from '@objectstack/spec/contracts';
4+
import type { Logger, LifecycleEventName } from '@objectstack/spec/contracts';
55

66
/**
77
* PluginContext - Runtime context available to plugins
@@ -58,18 +58,26 @@ export interface PluginContext {
5858
getServices(): Map<string, any>;
5959

6060
/**
61-
* Register a hook handler
61+
* Register a hook handler.
62+
*
63+
* Known lifecycle-bus names (see `IPluginLifecycleEvents` in
64+
* `@objectstack/spec`) autocomplete; the bus stays open to custom
65+
* cross-plugin event names, so any string remains valid.
66+
*
6267
* @param name - Hook name (e.g., 'kernel:ready', 'data:beforeInsert')
6368
* @param handler - Hook handler function
6469
*/
65-
hook(name: string, handler: (...args: any[]) => void | Promise<void>): void;
70+
hook(
71+
name: LifecycleEventName | (string & {}),
72+
handler: (...args: any[]) => void | Promise<void>,
73+
): void;
6674

6775
/**
6876
* Trigger a hook
69-
* @param name - Hook name
77+
* @param name - Hook name (known lifecycle names autocomplete; custom names stay legal)
7078
* @param args - Arguments to pass to hook handlers
7179
*/
72-
trigger(name: string, ...args: any[]): Promise<void>;
80+
trigger(name: LifecycleEventName | (string & {}), ...args: any[]): Promise<void>;
7381

7482
/**
7583
* Logger instance

packages/spec/PROTOCOL_MAP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ This document serves as the **Grand Map** of the ObjectStack specification. It l
202202
| [`plugin-validator.zod.ts`](src/kernel/plugin-validator.zod.ts) | | **Validation**. Integrity checks for plugins. |
203203
| [`plugin-structure.zod.ts`](src/kernel/plugin-structure.zod.ts) | | **Structure**. Zod rules for folder layout and file naming. |
204204
| [`plugin-capability.zod.ts`](src/kernel/plugin-capability.zod.ts) | | **Capabilities**. What a plugin can do. |
205-
| [`plugin-lifecycle-events.zod.ts`](src/kernel/plugin-lifecycle-events.zod.ts) | | **Lifecycle Events**. Hooks for plugin state changes. |
205+
| [`plugin-lifecycle-events.ts`](src/contracts/plugin-lifecycle-events.ts) | | **Lifecycle Events**. Registry of every kernel-bus event that actually fires, with payload tuples; feeds `hook`/`trigger` autocomplete. |
206206
| [`plugin-lifecycle-advanced.zod.ts`](src/kernel/plugin-lifecycle-advanced.zod.ts) | | **Advanced Lifecycle**. Health monitoring, hot reload state management, graceful degradation, and update strategies. |
207207
| [`plugin-security-advanced.zod.ts`](src/kernel/plugin-security-advanced.zod.ts) | | **Advanced Security**. Permission system, sandbox configuration (V8/WASM/container/process), security scanning, and trust levels. |
208208
| [`startup-orchestrator.zod.ts`](src/kernel/startup-orchestrator.zod.ts) | | **Startup**. Boot sequence orchestration. |

0 commit comments

Comments
 (0)