@holoscript/plugin-manufacturing-qc 2.0.1

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/src/runtime.ts ADDED
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Runtime integration for @holoscript/plugin-manufacturing-qc.
3
+ *
4
+ * Bridges the previously dead-wired `spc` trait into a behavioral
5
+ * TraitHandler that the HoloScript runtime actually dispatches
6
+ * (HoloScriptRuntime.registerTrait -> applyDirectives / updateTraits).
7
+ *
8
+ * Before this module the plugin declared trait NAMES only (pluginMeta.traits)
9
+ * and exported the SPC solvers (computeCapability, buildSPCChart, …), but
10
+ * nothing invoked a solver THROUGH the runtime — the whole domain-plugin tier
11
+ * was built-but-dead-wired. This mirrors government-civic-plugin's reference
12
+ * integration (civic_decision): it wires the deterministic Statistical Process
13
+ * Control capability solver (`computeCapability`) behind the `spc` trait so the
14
+ * runtime's directive dispatch can run it. The remaining manufacturing-qc
15
+ * traits follow the same registrar shape.
16
+ */
17
+ import { registerPluginTraits } from '@holoscript/core/runtime';
18
+ import {
19
+ computeCapability,
20
+ type Subgroup,
21
+ type ProcessCapability,
22
+ } from './spc';
23
+
24
+ /** Stable id for this plugin's trait ownership tagging. */
25
+ export const MANUFACTURING_QC_PLUGIN_ID = 'manufacturing-qc' as const;
26
+
27
+ /** Config carried by an orb's `@spc` trait directive. */
28
+ export interface SpcTraitConfig {
29
+ /** All individual measurements (flattened across subgroups). Required; absence emits `spc_error`. */
30
+ allValues?: number[];
31
+ /** Original subgroups (used for within-subgroup σ̂ via R̅/d₂). Required. */
32
+ subgroups?: Subgroup[];
33
+ /** Lower specification limit. Required. */
34
+ lsl?: number;
35
+ /** Upper specification limit. Required. */
36
+ usl?: number;
37
+ /** Nominal target (optional; used for Cpm). */
38
+ target?: number;
39
+ }
40
+
41
+ /** Summary payload emitted on `spc_solved`. */
42
+ export interface SpcSolvedEvent {
43
+ nodeId: string;
44
+ /** Potential capability index (short-term, within-subgroup σ̂). */
45
+ Cp: number;
46
+ /** Actual capability index (within-subgroup σ̂, accounts for centering). */
47
+ Cpk: number;
48
+ /** Estimated process mean. */
49
+ processMean: number;
50
+ /** Overall (long-term) process standard deviation. */
51
+ processStdDev: number;
52
+ /** Whether the process is capable (Cpk >= 1.33). */
53
+ capable: boolean;
54
+ /** Number of individual measurements evaluated. */
55
+ valueCount: number;
56
+ /** Number of subgroups supplied. */
57
+ subgroupCount: number;
58
+ }
59
+
60
+ /**
61
+ * Structural view of the runtime trait-handler contract. Matches
62
+ * `@holoscript/core` TraitTypes.TraitHandler at the call sites the runtime
63
+ * actually uses (onAttach / onUpdate receive the node, the directive config,
64
+ * and a context exposing `emit`). Declared locally so the plugin stays
65
+ * decoupled from core's full trait surface.
66
+ */
67
+ export interface TraitDispatchContext {
68
+ emit: (event: string, payload?: unknown) => void;
69
+ setState?: (updates: Record<string, unknown>) => void;
70
+ }
71
+
72
+ export interface RuntimeTraitHandler {
73
+ name: string;
74
+ onAttach?: (node: unknown, config: SpcTraitConfig, context: TraitDispatchContext) => void;
75
+ onUpdate?: (
76
+ node: unknown,
77
+ config: SpcTraitConfig,
78
+ context: TraitDispatchContext,
79
+ delta: number,
80
+ ) => void;
81
+ }
82
+
83
+ interface SpcNode {
84
+ id?: string;
85
+ name?: string;
86
+ properties?: Record<string, unknown>;
87
+ __spcResult?: ProcessCapability;
88
+ }
89
+
90
+ /** Run the SPC capability solver on the directive config, write the result onto the node, and emit. */
91
+ function solveOntoNode(
92
+ node: unknown,
93
+ config: SpcTraitConfig | undefined,
94
+ context: TraitDispatchContext,
95
+ ): void {
96
+ const carrier = node as SpcNode;
97
+ const nodeId = carrier.id ?? carrier.name ?? 'unknown';
98
+ const allValues = config?.allValues;
99
+ const subgroups = config?.subgroups;
100
+ const lsl = config?.lsl;
101
+ const usl = config?.usl;
102
+
103
+ if (
104
+ !Array.isArray(allValues) ||
105
+ !Array.isArray(subgroups) ||
106
+ typeof lsl !== 'number' ||
107
+ typeof usl !== 'number'
108
+ ) {
109
+ context.emit('spc_error', {
110
+ nodeId,
111
+ error:
112
+ 'spc trait requires config.allValues (number[]), config.subgroups (Subgroup[]), config.lsl (number) and config.usl (number)',
113
+ });
114
+ return;
115
+ }
116
+
117
+ try {
118
+ const result = computeCapability(allValues, subgroups, lsl, usl, config?.target);
119
+ carrier.__spcResult = result;
120
+ carrier.properties = {
121
+ ...(carrier.properties ?? {}),
122
+ spcCp: result.Cp,
123
+ spcCpk: result.Cpk,
124
+ spcCapable: result.capable,
125
+ };
126
+ const summary: SpcSolvedEvent = {
127
+ nodeId,
128
+ Cp: result.Cp,
129
+ Cpk: result.Cpk,
130
+ processMean: result.processMean,
131
+ processStdDev: result.processStdDev,
132
+ capable: result.capable,
133
+ valueCount: allValues.length,
134
+ subgroupCount: subgroups.length,
135
+ };
136
+ context.setState?.({ [`spc:${nodeId}`]: summary });
137
+ context.emit('spc_solved', summary);
138
+ } catch (error) {
139
+ context.emit('spc_error', {
140
+ nodeId,
141
+ error: error instanceof Error ? error.message : String(error),
142
+ });
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Behavioral handler for the manufacturing-qc `spc` trait. Runs the
148
+ * deterministic Statistical Process Control capability solver whenever an orb
149
+ * carrying the trait is attached (and on each per-frame update), writing the
150
+ * Cp/Cpk result onto the node and emitting `spc_solved` / `spc_error`.
151
+ */
152
+ export const spcHandler: RuntimeTraitHandler = {
153
+ name: 'spc',
154
+ onAttach: (node, config, context) => solveOntoNode(node, config, context),
155
+ onUpdate: (node, config, context) => solveOntoNode(node, config, context),
156
+ };
157
+
158
+ /** A runtime that can register behavioral trait handlers. */
159
+ export interface TraitRegistrar {
160
+ registerTrait(name: string, handler: unknown): void;
161
+ }
162
+
163
+ /**
164
+ * Register manufacturing-qc behavioral trait handlers into a runtime that
165
+ * exposes `registerTrait(name, handler)` — e.g. `@holoscript/core`
166
+ * HoloScriptRuntime. This is the consumption path the dead-wired tier was
167
+ * missing: after this call the runtime's directive dispatch (applyDirectives /
168
+ * updateTraits) will invoke the SPC capability solver for `@spc` orbs.
169
+ */
170
+ export function registerManufacturingQcTraitHandlers(registrar: TraitRegistrar): void {
171
+ registerPluginTraits(registrar, MANUFACTURING_QC_PLUGIN_ID, [spcHandler]);
172
+ }