@h-rig/core 0.0.6-alpha.134 → 0.0.6-alpha.136

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/dist/src/index.js CHANGED
@@ -190,6 +190,8 @@ function createPluginHost(plugins) {
190
190
  const taskFieldExtensions = [];
191
191
  const taskSources = [];
192
192
  const cliCommands = [];
193
+ const stageMutations = [];
194
+ const stageExecutors = {};
193
195
  const executableValidators = [];
194
196
  const executableTaskSources = [];
195
197
  for (const plugin of plugins) {
@@ -219,6 +221,10 @@ function createPluginHost(plugins) {
219
221
  taskSources.push(...c.taskSources.map((item) => ({ item, pluginName })));
220
222
  if (c.cliCommands)
221
223
  cliCommands.push(...c.cliCommands.map((item) => ({ item, pluginName })));
224
+ if (c.stageMutations)
225
+ stageMutations.push(...c.stageMutations.map((item) => ({ item, pluginName })));
226
+ if (plugin.__runtime?.stages)
227
+ Object.assign(stageExecutors, plugin.__runtime.stages);
222
228
  }
223
229
  indexById(executableValidators, "executableValidator");
224
230
  indexById(executableTaskSources, "executableTaskSource");
@@ -247,6 +253,7 @@ function createPluginHost(plugins) {
247
253
  const allTaskFieldExtensions = taskFieldExtensions.map((c) => c.item);
248
254
  const allTaskSources = taskSources.map((c) => c.item);
249
255
  const allCliCommands = cliCommands.map((c) => c.item);
256
+ const allStageMutations = stageMutations.map((c) => c.item);
250
257
  const allExecutableValidators = executableValidators.map((c) => c.item);
251
258
  const allExecutableTaskSources = executableTaskSources.map((c) => c.item);
252
259
  return {
@@ -266,6 +273,8 @@ function createPluginHost(plugins) {
266
273
  listTaskFieldExtensions: () => allTaskFieldExtensions,
267
274
  listTaskSources: () => allTaskSources,
268
275
  listCliCommands: () => allCliCommands,
276
+ listStageMutations: () => allStageMutations,
277
+ listStageExecutors: () => stageExecutors,
269
278
  listExecutableValidators: () => allExecutableValidators,
270
279
  listExecutableTaskSources: () => allExecutableTaskSources,
271
280
  resolveTaskSourceFactoryByKind: (kind) => taskSourceFactoryByKind.get(kind)
@@ -3058,6 +3067,19 @@ class PipelineUnresolvableError extends Error {
3058
3067
  this.contributors = contributors;
3059
3068
  }
3060
3069
  }
3070
+
3071
+ class ProtectedStageViolationError extends PipelineUnresolvableError {
3072
+ stageId;
3073
+ pluginId;
3074
+ op;
3075
+ constructor(stageId, pluginId, op) {
3076
+ super(`Protected stage ${stageId} cannot be ${op === "remove" ? "removed" : "replaced"} by ${pluginId} without an explicit grant`, [], [pluginId]);
3077
+ this.name = "ProtectedStageViolationError";
3078
+ this.stageId = stageId;
3079
+ this.pluginId = pluginId;
3080
+ this.op = op;
3081
+ }
3082
+ }
3061
3083
  function uniqueSorted(values) {
3062
3084
  return Array.from(new Set(values)).sort((left, right) => left.localeCompare(right));
3063
3085
  }
@@ -3256,7 +3278,7 @@ function resolveStagePipeline(input) {
3256
3278
  if (!state)
3257
3279
  continue;
3258
3280
  if (state.isProtected && !hasProtectedGrant(grants, mutation.id, contributor, "remove")) {
3259
- throw new PipelineUnresolvableError(`Protected stage ${mutation.id} cannot be removed by ${contributor} without an explicit grant`, [], [contributor]);
3281
+ throw new ProtectedStageViolationError(mutation.id, contributor, "remove");
3260
3282
  }
3261
3283
  const removedState = {
3262
3284
  ...state,
@@ -3272,7 +3294,7 @@ function resolveStagePipeline(input) {
3272
3294
  if (!state)
3273
3295
  continue;
3274
3296
  if (state.isProtected && !hasProtectedGrant(grants, mutation.id, contributor, "replace")) {
3275
- throw new PipelineUnresolvableError(`Protected stage ${mutation.id} cannot be replaced by ${contributor} without an explicit grant`, [], [contributor]);
3297
+ throw new ProtectedStageViolationError(mutation.id, contributor, "replace");
3276
3298
  }
3277
3299
  const replacement = { ...mutation.stage, id: mutation.id };
3278
3300
  states.set(mutation.id, {
@@ -1,4 +1,4 @@
1
- import type { ValidatorRegistration, HookRegistration, SkillRegistration, RepoSourceRegistration, AgentRoleRegistration, TaskFieldExtension, TaskSourceRegistration, CliCommandRegistration } from "@rig/contracts";
1
+ import type { ValidatorRegistration, HookRegistration, SkillRegistration, RepoSourceRegistration, AgentRoleRegistration, TaskFieldExtension, TaskSourceRegistration, CliCommandRegistration, StageMutation, StageRun } from "@rig/contracts";
2
2
  import type { RegisteredValidator, RigPluginWithRuntime, TaskSourceFactoryEntry } from "./plugin-runtime";
3
3
  export interface PluginHost {
4
4
  getValidator(id: string): ValidatorRegistration | undefined;
@@ -17,6 +17,19 @@ export interface PluginHost {
17
17
  listTaskFieldExtensions(): readonly TaskFieldExtension[];
18
18
  listTaskSources(): readonly TaskSourceRegistration[];
19
19
  listCliCommands(): readonly CliCommandRegistration[];
20
+ /**
21
+ * Stage mutations contributed by all loaded plugins, flattened in load order.
22
+ * The kernel resolves these (+ the default-lifecycle stages) into the run
23
+ * pipeline — this is the wire that makes "every plugin mutates the lifecycle"
24
+ * real (drift pre-merge gate, closure observer, reclassify observer).
25
+ */
26
+ listStageMutations(): readonly StageMutation[];
27
+ /**
28
+ * Executable stage implementations contributed by plugins (`runtime.stages`),
29
+ * merged by stage id. The kernel's stage runner uses these to execute
30
+ * plugin-contributed stages inserted via stageMutations.
31
+ */
32
+ listStageExecutors(): Readonly<Record<string, StageRun>>;
20
33
  /**
21
34
  * Executable validators contributed by plugins. Only validators whose
22
35
  * metadata appears in `listValidators()` and whose plugin shipped a runtime
@@ -90,6 +90,8 @@ function createPluginHost(plugins) {
90
90
  const taskFieldExtensions = [];
91
91
  const taskSources = [];
92
92
  const cliCommands = [];
93
+ const stageMutations = [];
94
+ const stageExecutors = {};
93
95
  const executableValidators = [];
94
96
  const executableTaskSources = [];
95
97
  for (const plugin of plugins) {
@@ -119,6 +121,10 @@ function createPluginHost(plugins) {
119
121
  taskSources.push(...c.taskSources.map((item) => ({ item, pluginName })));
120
122
  if (c.cliCommands)
121
123
  cliCommands.push(...c.cliCommands.map((item) => ({ item, pluginName })));
124
+ if (c.stageMutations)
125
+ stageMutations.push(...c.stageMutations.map((item) => ({ item, pluginName })));
126
+ if (plugin.__runtime?.stages)
127
+ Object.assign(stageExecutors, plugin.__runtime.stages);
122
128
  }
123
129
  indexById(executableValidators, "executableValidator");
124
130
  indexById(executableTaskSources, "executableTaskSource");
@@ -147,6 +153,7 @@ function createPluginHost(plugins) {
147
153
  const allTaskFieldExtensions = taskFieldExtensions.map((c) => c.item);
148
154
  const allTaskSources = taskSources.map((c) => c.item);
149
155
  const allCliCommands = cliCommands.map((c) => c.item);
156
+ const allStageMutations = stageMutations.map((c) => c.item);
150
157
  const allExecutableValidators = executableValidators.map((c) => c.item);
151
158
  const allExecutableTaskSources = executableTaskSources.map((c) => c.item);
152
159
  return {
@@ -166,6 +173,8 @@ function createPluginHost(plugins) {
166
173
  listTaskFieldExtensions: () => allTaskFieldExtensions,
167
174
  listTaskSources: () => allTaskSources,
168
175
  listCliCommands: () => allCliCommands,
176
+ listStageMutations: () => allStageMutations,
177
+ listStageExecutors: () => stageExecutors,
169
178
  listExecutableValidators: () => allExecutableValidators,
170
179
  listExecutableTaskSources: () => allExecutableTaskSources,
171
180
  resolveTaskSourceFactoryByKind: (kind) => taskSourceFactoryByKind.get(kind)
@@ -1,4 +1,4 @@
1
- import type { HookImplementation, RegisteredTaskSource, RigConfig, RigPlugin, TaskSourceConfig, TaskSourceRegistration, ValidatorRegistration } from "@rig/contracts";
1
+ import type { HookImplementation, RegisteredTaskSource, RigConfig, RigPlugin, StageRun, TaskSourceConfig, TaskSourceRegistration, ValidatorRegistration } from "@rig/contracts";
2
2
  export interface ValidatorResult {
3
3
  id: string;
4
4
  passed: boolean;
@@ -58,6 +58,14 @@ export interface RigPluginRuntime {
58
58
  * `@rig/runtime/control-plane/hook-runner`).
59
59
  */
60
60
  hooks?: Record<string, HookImplementation>;
61
+ /**
62
+ * Executable stage implementations keyed by stage id — the runtime counterpart
63
+ * to `contributes.stageMutations` (which carries only the ordering descriptor).
64
+ * When a plugin inserts/replaces a stage, its `run(ctx)` lives here. The plugin
65
+ * host flattens these (`listStageExecutors()`) so the kernel's stage runner can
66
+ * execute plugin-contributed stages (e.g. the docs-drift pre-merge gate).
67
+ */
68
+ stages?: Record<string, StageRun>;
61
69
  }
62
70
  export type RigPluginWithRuntime = RigPlugin & {
63
71
  __runtime?: RigPluginRuntime;
@@ -81,4 +81,17 @@ export declare class PipelineUnresolvableError extends Error {
81
81
  readonly contributors: readonly string[];
82
82
  constructor(message: string, cycles: readonly (readonly string[])[], contributors: readonly string[]);
83
83
  }
84
+ /**
85
+ * Raised when a plugin attempts to `remove`/`replace` a protected stage without
86
+ * an explicit grant. Subclasses {@link PipelineUnresolvableError} so existing
87
+ * `instanceof PipelineUnresolvableError` checks keep working, but carries the
88
+ * stage/plugin/op so the kernel layer can surface the typed contracts
89
+ * `ProtectedStageViolation` (with its `KernelBootErrorCode`).
90
+ */
91
+ export declare class ProtectedStageViolationError extends PipelineUnresolvableError {
92
+ readonly stageId: string;
93
+ readonly pluginId: string;
94
+ readonly op: "remove" | "replace";
95
+ constructor(stageId: string, pluginId: string, op: "remove" | "replace");
96
+ }
84
97
  export declare function resolveStagePipeline<TStage extends ResolvableStage>(input: ResolveStagePipelineInput<TStage>): ResolvedStagePipeline<TStage>;
@@ -10,6 +10,19 @@ class PipelineUnresolvableError extends Error {
10
10
  this.contributors = contributors;
11
11
  }
12
12
  }
13
+
14
+ class ProtectedStageViolationError extends PipelineUnresolvableError {
15
+ stageId;
16
+ pluginId;
17
+ op;
18
+ constructor(stageId, pluginId, op) {
19
+ super(`Protected stage ${stageId} cannot be ${op === "remove" ? "removed" : "replaced"} by ${pluginId} without an explicit grant`, [], [pluginId]);
20
+ this.name = "ProtectedStageViolationError";
21
+ this.stageId = stageId;
22
+ this.pluginId = pluginId;
23
+ this.op = op;
24
+ }
25
+ }
13
26
  function uniqueSorted(values) {
14
27
  return Array.from(new Set(values)).sort((left, right) => left.localeCompare(right));
15
28
  }
@@ -208,7 +221,7 @@ function resolveStagePipeline(input) {
208
221
  if (!state)
209
222
  continue;
210
223
  if (state.isProtected && !hasProtectedGrant(grants, mutation.id, contributor, "remove")) {
211
- throw new PipelineUnresolvableError(`Protected stage ${mutation.id} cannot be removed by ${contributor} without an explicit grant`, [], [contributor]);
224
+ throw new ProtectedStageViolationError(mutation.id, contributor, "remove");
212
225
  }
213
226
  const removedState = {
214
227
  ...state,
@@ -224,7 +237,7 @@ function resolveStagePipeline(input) {
224
237
  if (!state)
225
238
  continue;
226
239
  if (state.isProtected && !hasProtectedGrant(grants, mutation.id, contributor, "replace")) {
227
- throw new PipelineUnresolvableError(`Protected stage ${mutation.id} cannot be replaced by ${contributor} without an explicit grant`, [], [contributor]);
240
+ throw new ProtectedStageViolationError(mutation.id, contributor, "replace");
228
241
  }
229
242
  const replacement = { ...mutation.stage, id: mutation.id };
230
243
  states.set(mutation.id, {
@@ -371,5 +384,6 @@ function resolveStagePipeline(input) {
371
384
  }
372
385
  export {
373
386
  resolveStagePipeline,
387
+ ProtectedStageViolationError,
374
388
  PipelineUnresolvableError
375
389
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h-rig/core",
3
- "version": "0.0.6-alpha.134",
3
+ "version": "0.0.6-alpha.136",
4
4
  "type": "module",
5
5
  "description": "Config and plugin composition library for Rig's OMP extension ecosystem; not a product host/runtime.",
6
6
  "license": "UNLICENSED",
@@ -45,7 +45,7 @@
45
45
  "module": "./dist/src/index.js",
46
46
  "types": "./dist/src/index.d.ts",
47
47
  "dependencies": {
48
- "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.134",
49
- "effect": "4.0.0-beta.78"
48
+ "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.136",
49
+ "effect": "https://pkg.pr.new/Effect-TS/effect-smol/effect@8881a9b"
50
50
  }
51
51
  }