@shardworks/nexus 0.1.269 → 0.1.271

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/README.md CHANGED
@@ -119,6 +119,21 @@ Framework commands are defined in the CLI package itself (`src/commands/`). They
119
119
  | `nsg plugin remove <name>` | Remove a plugin |
120
120
  | `nsg plugin upgrade <name>` | Upgrade a plugin to a newer version *(stub)* |
121
121
 
122
+ ### Event Emission
123
+
124
+ | Command | Description |
125
+ |---|---|
126
+ | `nsg signal <name> [--payload '<json>']` | Emit a custom event into the Clockworks events book with `emitter='operator'` |
127
+
128
+ `nsg signal` is hand-written rather than auto-generated from the
129
+ clockworks `signal` tool — the auto-builder cannot JSON-parse a
130
+ record-shaped `--payload` flag, and the operator emitter default
131
+ differs from the tool's `'anima'` default. The event name must be
132
+ declared under `clockworks.events` in `guild.json`; reserved framework
133
+ namespaces (`anima.`, `commission.`, `migration.`, `guild.`,
134
+ `standing-order.`, `session.`) and writ-lifecycle patterns
135
+ (`<type>.{ready,completed,stuck,failed}`) are rejected.
136
+
122
137
  #### `nsg init`
123
138
 
124
139
  Writes the minimum viable guild. Does not run `git init`, create the database, or instantiate animas — those are separate steps.
@@ -248,7 +263,6 @@ The following commands are planned but not yet implemented. No plugin currently
248
263
  | `nsg anima update` | — | *(Planned)* Update anima configuration |
249
264
  | `nsg anima remove` | — | *(Planned)* Retire an anima |
250
265
  | `nsg anima manifest` | — | *(Planned)* Preview the manifest for an anima |
251
- | `nsg signal` | — | *(Planned)* Signal a custom event |
252
266
  | `nsg event list` | — | *(Planned)* List recent events |
253
267
  | `nsg event show` | — | *(Planned)* Show event detail |
254
268
  | `nsg dispatch list` | — | *(Planned)* List recent dispatches |
@@ -0,0 +1,225 @@
1
+ /**
2
+ * nsg clock — operator-facing Clockworks CLI.
3
+ *
4
+ * Three subcommands under `nsg clock` that compose on top of
5
+ * `ClockworksApi.processEvents` and a direct read of the
6
+ * `clockworks/events` book:
7
+ *
8
+ * - `nsg clock list` — print pending events (or, with
9
+ * `--include-processed`, every event), one event per two-line
10
+ * block (or a single line when payload is null), in id-ascending
11
+ * order. `--limit N` caps output at N entries.
12
+ * - `nsg clock tick [id]` — process a single event. Without `id`,
13
+ * the next pending event in id order; with `id`, exactly that
14
+ * event after a CLI-side pre-check that it exists and is still
15
+ * pending. Prints per-dispatch summary lines via the
16
+ * `processEvents({ onDispatch })` observer.
17
+ * - `nsg clock run` — loop `processEvents()` until the dispatcher
18
+ * reports zero processed events for an iteration. No sleep, no
19
+ * daemon — finite drain. Mid-sweep arrivals are picked up on the
20
+ * next iteration.
21
+ *
22
+ * The CLI package deliberately does not depend on the clockworks or
23
+ * stacks plugin packages — apparatus interfaces are declared inline
24
+ * and resolved at runtime via `guild().apparatus<T>(name)`. This
25
+ * mirrors the discipline practiced by `signal` and `start`.
26
+ *
27
+ * Hand-written rather than auto-built because:
28
+ * - `tick [id]` is an optional positional, which the auto-builder
29
+ * cannot express.
30
+ * - `--include-processed` and `--limit <N>` need locally-validated
31
+ * parsing.
32
+ * - Exit-code semantics are nontrivial: nonzero only when at least
33
+ * one dispatch recorded `status: error`, plus the
34
+ * missing-event-id and already-processed-event branches.
35
+ *
36
+ * See commission c-mody57g7 decisions D1–D20.
37
+ */
38
+ import { Command } from 'commander';
39
+ import { type ClockStatus } from '@shardworks/clockworks-apparatus';
40
+ interface DispatchObservationLike {
41
+ eventId: string;
42
+ eventName: string;
43
+ handlerName: string;
44
+ /**
45
+ * Mirrors `DispatchObservation.status` from the clockworks
46
+ * apparatus. The `'skipped'` variant covers loop-guard
47
+ * suppression — the relay was not invoked, no SOF was emitted, and
48
+ * `error` carries the loop-guard reason. Skipped rows must not
49
+ * count toward operator error metrics or the CLI exit code.
50
+ */
51
+ status: 'success' | 'error' | 'skipped';
52
+ durationMs: number;
53
+ error: string | null;
54
+ }
55
+ interface EventDocLike {
56
+ id: string;
57
+ name: string;
58
+ payload: unknown;
59
+ emitter: string;
60
+ firedAt: string;
61
+ processed: boolean;
62
+ }
63
+ /**
64
+ * Render the payload preview for `list`. Returns null when the
65
+ * payload is exactly null (D19 — payload line omitted entirely);
66
+ * otherwise returns a truncated JSON string.
67
+ */
68
+ export declare function renderPayloadPreview(payload: unknown): string | null;
69
+ /**
70
+ * Format a single event for `nsg clock list`. Two lines when payload
71
+ * is non-null; single line otherwise.
72
+ */
73
+ export declare function formatEventBlock(event: EventDocLike): string;
74
+ /**
75
+ * Format a single dispatch observation for the per-dispatch summary
76
+ * line emitted by `tick` and `run`. Per D10:
77
+ * `[<handlerName>] <status> <durationMs>ms`
78
+ * With `: <error>` appended on the same line when `status` is error.
79
+ *
80
+ * Loop-guard `'skipped'` rows render as
81
+ * `[<handlerName>] skipped: <loop-guard reason>`
82
+ * — the same colon-then-message convention as the error arm so output
83
+ * stays parseable. Skipped lines do NOT include a duration (the
84
+ * dispatcher never invoked the relay; surfacing `0ms` would only
85
+ * mislead operators).
86
+ */
87
+ export declare function formatDispatchLine(obs: DispatchObservationLike): string;
88
+ export interface ListInput {
89
+ /** Include processed events in addition to pending ones. */
90
+ includeProcessed?: boolean;
91
+ /** Cap output at this many entries; no default — undefined prints all. */
92
+ limit?: number;
93
+ }
94
+ export interface ListOutput {
95
+ /** Lines to print (already formatted). */
96
+ lines: string[];
97
+ /** Number of events rendered (after the limit cap, after the filter). */
98
+ count: number;
99
+ /** Whether the queue (matching the filter) was empty. */
100
+ empty: boolean;
101
+ }
102
+ /**
103
+ * Read events for `nsg clock list` and render them.
104
+ *
105
+ * The book read uses `find` with a `where` filter when only pending
106
+ * events are wanted (the common case); otherwise `list` with no
107
+ * filter (the `--include-processed` path).
108
+ */
109
+ export declare function runList(input: ListInput): Promise<ListOutput>;
110
+ export interface TickInput {
111
+ /** Optional event id to process. When omitted, the next pending event. */
112
+ eventId?: string;
113
+ }
114
+ export interface TickOutput {
115
+ /** Lines to print (in order). */
116
+ lines: string[];
117
+ /** Whether at least one dispatch row recorded `status: error`. */
118
+ hadError: boolean;
119
+ /** Whether the targeted/queue lookup found nothing to do. */
120
+ empty: boolean;
121
+ /** Set when an explicit eventId was supplied but does not exist. */
122
+ notFound: boolean;
123
+ /** Set when an explicit eventId was supplied but is already processed. */
124
+ alreadyProcessed: boolean;
125
+ /**
126
+ * Warning lines to write to stderr before the main output. Currently
127
+ * carries the daemon-coexistence warning when `nsg clock start` is
128
+ * already running.
129
+ */
130
+ warnings: string[];
131
+ }
132
+ /**
133
+ * Process a single event via `processEvents({ eventId })` or
134
+ * `processEvents({ max: 1 })` and capture the per-dispatch summary
135
+ * lines via the observer.
136
+ *
137
+ * The `events.get(id)` pre-check happens here per D4: missing-id and
138
+ * already-processed cases never reach the dispatcher.
139
+ */
140
+ export declare function runTick(input: TickInput): Promise<TickOutput>;
141
+ export interface RunOutput {
142
+ /** Lines to print (in dispatch order, plus the final count). */
143
+ lines: string[];
144
+ /** Whether at least one dispatch row across every iteration was an error. */
145
+ hadError: boolean;
146
+ /** Total events processed across all iterations. */
147
+ totalProcessed: number;
148
+ /** Whether the very first iteration found an empty queue. */
149
+ empty: boolean;
150
+ /**
151
+ * Warning lines to write to stderr before the main output. Currently
152
+ * carries the daemon-coexistence warning when `nsg clock start` is
153
+ * already running.
154
+ */
155
+ warnings: string[];
156
+ }
157
+ /**
158
+ * Drain the queue. Loop `processEvents()` until it reports zero
159
+ * processed events for an iteration. No sleep, no daemon. Per-dispatch
160
+ * summary lines emit as they happen via the observer; the final
161
+ * `processed N events` line goes out at the end.
162
+ */
163
+ export declare function runRun(): Promise<RunOutput>;
164
+ export interface StartInput {
165
+ /** Polling interval in milliseconds. Forwarded to `clockStart`. */
166
+ interval?: number;
167
+ /**
168
+ * When `true`, run the inline foreground daemon body instead of
169
+ * spawning a detached child. The detached `clock start` re-execs
170
+ * itself with this flag.
171
+ */
172
+ foreground?: boolean;
173
+ }
174
+ export interface StartOutput {
175
+ /** Lines to print. */
176
+ lines: string[];
177
+ }
178
+ /**
179
+ * Handle `nsg clock start`. Without `--foreground`, calls
180
+ * `clockStart(home)`, which spawns a detached child and blocks until
181
+ * the daemon is verified running. With `--foreground`, calls
182
+ * `runForegroundDaemonFromGuild` — the inline daemon body that the
183
+ * detached spawn re-execs into. The function returns only when the
184
+ * daemon shuts down (under SIGTERM or SIGINT).
185
+ */
186
+ export declare function runStart(input: StartInput): Promise<StartOutput>;
187
+ export interface StopOutput {
188
+ /** Lines to print. */
189
+ lines: string[];
190
+ }
191
+ /**
192
+ * Handle `nsg clock stop`. Thin wrapper around `clockStop`.
193
+ *
194
+ * Per spec: missing-pidfile and stale-pidfile cases exit zero with a
195
+ * message — they are not errors. The success-path message comes from
196
+ * the core API result so the three branches (`'signaled'`,
197
+ * `'no-pidfile'`, `'stale'`) stay aligned across CLI / programmatic
198
+ * consumers.
199
+ */
200
+ export declare function runStop(): Promise<StopOutput>;
201
+ export interface StatusInput {
202
+ /** Emit JSON instead of multi-line plain text. */
203
+ json?: boolean;
204
+ }
205
+ export interface StatusOutput {
206
+ /** Lines to print. */
207
+ lines: string[];
208
+ /** The structured status, included unconditionally so tests can assert it. */
209
+ status: ClockStatus;
210
+ }
211
+ /**
212
+ * Handle `nsg clock status`. Defaults to multi-line plain text;
213
+ * `--json` emits the structured shape verbatim. The output mirrors
214
+ * the `clock-status` MCP tool's payload so the surfaces stay aligned.
215
+ */
216
+ export declare function runStatus(input: StatusInput): StatusOutput;
217
+ /**
218
+ * Build the `nsg clock` Commander Command — the parent group plus the
219
+ * three subcommands. Each subcommand's action wrapper translates the
220
+ * structured handler output to printed lines and `process.exit(N)` per
221
+ * commission decision D8.
222
+ */
223
+ export declare function buildClockCommand(): Command;
224
+ export {};
225
+ //# sourceMappingURL=clock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../../src/commands/clock.ts"],"names":[],"mappings":"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"}