@h-rig/core 0.0.6-alpha.15 → 0.0.6-alpha.151
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/config.d.ts +3 -0
- package/dist/src/config.js +136 -0
- package/dist/src/define-config.d.ts +18 -0
- package/dist/src/define-config.js +20 -2
- package/dist/src/define-plugin.d.ts +9 -0
- package/dist/src/define-plugin.js +48 -0
- package/dist/src/dependencyGraph.d.ts +43 -0
- package/dist/src/dependencyGraph.js +703 -0
- package/dist/src/engineReadModelReducer.d.ts +12 -0
- package/dist/src/engineReadModelReducer.js +17 -13
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.js +1319 -43
- package/dist/src/load-config.d.ts +2 -0
- package/dist/src/load-config.js +308 -4
- package/dist/src/plugin-host.d.ts +65 -0
- package/dist/src/plugin-host.js +134 -0
- package/dist/src/plugin-runtime.d.ts +105 -0
- package/dist/src/rig-init-builder.d.ts +30 -0
- package/dist/src/rig-init-builder.js +15 -11
- package/dist/src/rigSelectors.d.ts +220 -0
- package/dist/src/rigSelectors.js +125 -4
- package/dist/src/rollups.d.ts +6 -0
- package/dist/src/rollups.js +377 -0
- package/dist/src/stageResolve.d.ts +77 -0
- package/dist/src/stageResolve.js +361 -0
- package/dist/src/taskGraph.d.ts +64 -0
- package/dist/src/taskGraph.js +321 -8
- package/dist/src/taskGraphCodes.d.ts +3 -0
- package/dist/src/taskGraphLayout.d.ts +61 -0
- package/dist/src/taskGraphLayout.js +27 -4
- package/dist/src/taskScore.d.ts +17 -0
- package/dist/src/taskScore.js +49 -0
- package/package.json +28 -10
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { defineConfig, type RigConfigInput } from "./define-config";
|
|
2
|
+
export { definePlugin } from "./define-plugin";
|
|
3
|
+
export type { RegisteredValidator, RigPluginRuntime, RigPluginWithRuntime, RuntimeCliCommand, RuntimeCliContext, RuntimePanelProducer, TaskSourceFactoryContext, TaskSourceFactoryEntry, ValidatorContext, ValidatorResult, } from "./plugin-runtime";
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/core/src/define-config.ts
|
|
3
|
+
import { Schema } from "effect";
|
|
4
|
+
import { RigConfig } from "@rig/contracts";
|
|
5
|
+
function normalizeWorkspaceConfig(raw) {
|
|
6
|
+
const workspace = raw && typeof raw === "object" && !Array.isArray(raw) ? { ...raw } : { mainRepo: "." };
|
|
7
|
+
workspace.checkout = workspace.checkout ?? workspace.isolation ?? "worktree";
|
|
8
|
+
workspace.isolation = workspace.isolation ?? workspace.checkout;
|
|
9
|
+
workspace.sandbox = workspace.sandbox ?? "enforce";
|
|
10
|
+
return workspace;
|
|
11
|
+
}
|
|
12
|
+
function applyConfigDefaults(raw) {
|
|
13
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
14
|
+
return raw;
|
|
15
|
+
const record = raw;
|
|
16
|
+
return {
|
|
17
|
+
...record,
|
|
18
|
+
plugins: Array.isArray(record.plugins) ? record.plugins : [],
|
|
19
|
+
workspace: normalizeWorkspaceConfig(record.workspace)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function defineConfig(cfg) {
|
|
23
|
+
const runtimeByName = new Map;
|
|
24
|
+
const plugins = cfg.plugins ?? [];
|
|
25
|
+
for (const plugin of plugins) {
|
|
26
|
+
if (plugin?.__runtime) {
|
|
27
|
+
runtimeByName.set(plugin.name, plugin.__runtime);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const decoded = Schema.decodeUnknownSync(RigConfig)(applyConfigDefaults(cfg));
|
|
31
|
+
const decodedPlugins = decoded.plugins.map((p) => {
|
|
32
|
+
const runtime = runtimeByName.get(p.name);
|
|
33
|
+
if (!runtime)
|
|
34
|
+
return p;
|
|
35
|
+
return { ...p, __runtime: runtime };
|
|
36
|
+
});
|
|
37
|
+
return { ...decoded, plugins: decodedPlugins };
|
|
38
|
+
}
|
|
39
|
+
// packages/core/src/define-plugin.ts
|
|
40
|
+
import { Schema as Schema2 } from "effect";
|
|
41
|
+
import { RigPlugin } from "@rig/contracts";
|
|
42
|
+
function definePlugin(meta, runtime) {
|
|
43
|
+
const validated = Schema2.decodeUnknownSync(RigPlugin)(meta);
|
|
44
|
+
if (!runtime) {
|
|
45
|
+
return validated;
|
|
46
|
+
}
|
|
47
|
+
const declaredValidators = new Map((validated.contributes?.validators ?? []).map((v) => [v.id, v]));
|
|
48
|
+
const runtimeValidators = new Map((runtime.validators ?? []).map((v) => [v.id, v]));
|
|
49
|
+
for (const v of runtimeValidators.values()) {
|
|
50
|
+
const metadata = declaredValidators.get(v.id);
|
|
51
|
+
if (!metadata) {
|
|
52
|
+
throw new Error(`definePlugin(${validated.name}): executable validator "${v.id}" has no matching metadata entry in contributes.validators`);
|
|
53
|
+
}
|
|
54
|
+
if (metadata.category !== v.category) {
|
|
55
|
+
throw new Error(`definePlugin(${validated.name}): executable validator "${v.id}" category "${v.category}" does not match metadata category "${metadata.category}"`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (runtime.validators) {
|
|
59
|
+
for (const v of declaredValidators.values()) {
|
|
60
|
+
if (!runtimeValidators.has(v.id)) {
|
|
61
|
+
throw new Error(`definePlugin(${validated.name}): validator metadata "${v.id}" has no runtime implementation`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const declaredSources = new Map((validated.contributes?.taskSources ?? []).map((s) => [s.id, s]));
|
|
66
|
+
const runtimeSources = new Map((runtime.taskSources ?? []).map((s) => [s.id, s]));
|
|
67
|
+
for (const s of runtimeSources.values()) {
|
|
68
|
+
const metadata = declaredSources.get(s.id);
|
|
69
|
+
if (!metadata) {
|
|
70
|
+
throw new Error(`definePlugin(${validated.name}): executable task source "${s.id}" has no matching metadata entry in contributes.taskSources`);
|
|
71
|
+
}
|
|
72
|
+
if (metadata.kind !== s.kind) {
|
|
73
|
+
throw new Error(`definePlugin(${validated.name}): executable task source "${s.id}" kind "${s.kind}" does not match metadata kind "${metadata.kind}"`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (runtime.taskSources) {
|
|
77
|
+
for (const s of declaredSources.values()) {
|
|
78
|
+
if (!runtimeSources.has(s.id)) {
|
|
79
|
+
throw new Error(`definePlugin(${validated.name}): task source metadata "${s.id}" has no runtime implementation`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const declaredHooks = new Map((validated.contributes?.hooks ?? []).map((h) => [h.id, h]));
|
|
84
|
+
for (const hookId of Object.keys(runtime.hooks ?? {})) {
|
|
85
|
+
const metadata = declaredHooks.get(hookId);
|
|
86
|
+
if (!metadata) {
|
|
87
|
+
throw new Error(`definePlugin(${validated.name}): typed hook "${hookId}" has no matching metadata entry in contributes.hooks`);
|
|
88
|
+
}
|
|
89
|
+
if (metadata.command) {
|
|
90
|
+
throw new Error(`definePlugin(${validated.name}): hook "${hookId}" has both a typed implementation and a command string \u2014 pick one`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (runtime.hooks) {
|
|
94
|
+
for (const h of declaredHooks.values()) {
|
|
95
|
+
if (!runtime.hooks[h.id] && !h.command) {
|
|
96
|
+
throw new Error(`definePlugin(${validated.name}): hook metadata "${h.id}" has no implementation (typed function or command)`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const declaredCapabilities = new Map((validated.contributes?.capabilities ?? []).map((capability) => [capability.id, capability]));
|
|
101
|
+
for (const capability of runtime.featureCapabilities ?? []) {
|
|
102
|
+
if (!declaredCapabilities.has(capability.id)) {
|
|
103
|
+
throw new Error(`definePlugin(${validated.name}): executable capability "${capability.id}" has no matching metadata entry in contributes.capabilities`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const declaredPanels = new Map((validated.contributes?.panels ?? []).map((panel) => [panel.id, panel]));
|
|
107
|
+
for (const panel of runtime.panels ?? []) {
|
|
108
|
+
const metadata = declaredPanels.get(panel.id);
|
|
109
|
+
if (!metadata) {
|
|
110
|
+
throw new Error(`definePlugin(${validated.name}): executable panel "${panel.id}" has no matching metadata entry in contributes.panels`);
|
|
111
|
+
}
|
|
112
|
+
if (metadata.slot !== panel.slot) {
|
|
113
|
+
throw new Error(`definePlugin(${validated.name}): executable panel "${panel.id}" slot "${panel.slot}" does not match metadata slot "${metadata.slot}"`);
|
|
114
|
+
}
|
|
115
|
+
if (metadata.capabilityId !== panel.capabilityId) {
|
|
116
|
+
throw new Error(`definePlugin(${validated.name}): executable panel "${panel.id}" capabilityId "${panel.capabilityId ?? "(none)"}" does not match metadata capabilityId "${metadata.capabilityId ?? "(none)"}"`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const declaredBlockerClassifiers = new Map((validated.contributes?.blockerClassifiers ?? []).map((classifier) => [classifier.id, classifier]));
|
|
120
|
+
for (const classifier of runtime.blockerClassifiers ?? []) {
|
|
121
|
+
if (!declaredBlockerClassifiers.has(classifier.id)) {
|
|
122
|
+
throw new Error(`definePlugin(${validated.name}): executable blocker classifier "${classifier.id}" has no matching metadata entry in contributes.blockerClassifiers`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const declaredCliCommands = new Map((validated.contributes?.cliCommands ?? []).map((command) => [command.id, command]));
|
|
126
|
+
for (const command of runtime.cliCommands ?? []) {
|
|
127
|
+
if (!declaredCliCommands.has(command.id)) {
|
|
128
|
+
throw new Error(`definePlugin(${validated.name}): executable cli command "${command.id}" has no matching metadata entry in contributes.cliCommands`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return { ...validated, __runtime: runtime };
|
|
132
|
+
}
|
|
133
|
+
export {
|
|
134
|
+
definePlugin,
|
|
135
|
+
defineConfig
|
|
136
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { RigConfig } from "@rig/contracts";
|
|
2
|
+
/**
|
|
3
|
+
* Author-facing config input: `plugins` and `workspace` are optional and
|
|
4
|
+
* default to a plugin-less worktree setup, so the minimal documented config
|
|
5
|
+
* (project + taskSource) works out of the box.
|
|
6
|
+
*/
|
|
7
|
+
export type RigConfigInput = Omit<RigConfig, "plugins" | "workspace"> & {
|
|
8
|
+
plugins?: RigConfig["plugins"];
|
|
9
|
+
workspace?: RigConfig["workspace"];
|
|
10
|
+
};
|
|
11
|
+
/** Fill optional top-level sections before Schema decode (which requires them). */
|
|
12
|
+
export declare function applyConfigDefaults(raw: unknown): unknown;
|
|
13
|
+
/**
|
|
14
|
+
* Validate a Rig config and decode through Schema, preserving each plugin's
|
|
15
|
+
* `__runtime` channel. Schema decode strips unknown fields, so we capture
|
|
16
|
+
* the runtime objects before decoding and re-attach them after.
|
|
17
|
+
*/
|
|
18
|
+
export declare function defineConfig(cfg: RigConfigInput): RigConfig;
|
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
// packages/core/src/define-config.ts
|
|
3
3
|
import { Schema } from "effect";
|
|
4
4
|
import { RigConfig } from "@rig/contracts";
|
|
5
|
+
function normalizeWorkspaceConfig(raw) {
|
|
6
|
+
const workspace = raw && typeof raw === "object" && !Array.isArray(raw) ? { ...raw } : { mainRepo: "." };
|
|
7
|
+
workspace.checkout = workspace.checkout ?? workspace.isolation ?? "worktree";
|
|
8
|
+
workspace.isolation = workspace.isolation ?? workspace.checkout;
|
|
9
|
+
workspace.sandbox = workspace.sandbox ?? "enforce";
|
|
10
|
+
return workspace;
|
|
11
|
+
}
|
|
12
|
+
function applyConfigDefaults(raw) {
|
|
13
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
14
|
+
return raw;
|
|
15
|
+
const record = raw;
|
|
16
|
+
return {
|
|
17
|
+
...record,
|
|
18
|
+
plugins: Array.isArray(record.plugins) ? record.plugins : [],
|
|
19
|
+
workspace: normalizeWorkspaceConfig(record.workspace)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
5
22
|
function defineConfig(cfg) {
|
|
6
23
|
const runtimeByName = new Map;
|
|
7
24
|
const plugins = cfg.plugins ?? [];
|
|
@@ -10,7 +27,7 @@ function defineConfig(cfg) {
|
|
|
10
27
|
runtimeByName.set(plugin.name, plugin.__runtime);
|
|
11
28
|
}
|
|
12
29
|
}
|
|
13
|
-
const decoded = Schema.decodeUnknownSync(RigConfig)(cfg);
|
|
30
|
+
const decoded = Schema.decodeUnknownSync(RigConfig)(applyConfigDefaults(cfg));
|
|
14
31
|
const decodedPlugins = decoded.plugins.map((p) => {
|
|
15
32
|
const runtime = runtimeByName.get(p.name);
|
|
16
33
|
if (!runtime)
|
|
@@ -20,5 +37,6 @@ function defineConfig(cfg) {
|
|
|
20
37
|
return { ...decoded, plugins: decodedPlugins };
|
|
21
38
|
}
|
|
22
39
|
export {
|
|
23
|
-
defineConfig
|
|
40
|
+
defineConfig,
|
|
41
|
+
applyConfigDefaults
|
|
24
42
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RigPlugin } from "@rig/contracts";
|
|
2
|
+
import type { RigPluginRuntime, RigPluginWithRuntime } from "./plugin-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Define a Rig plugin. The first argument is the schema-validated metadata
|
|
5
|
+
* (id strings, version, contributions). The optional second argument carries
|
|
6
|
+
* executable bits (validator `run` functions, etc.) that Schema cannot
|
|
7
|
+
* represent — they travel alongside the validated metadata as `__runtime`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function definePlugin(meta: RigPlugin, runtime?: RigPluginRuntime): RigPluginWithRuntime;
|
|
@@ -43,6 +43,54 @@ function definePlugin(meta, runtime) {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
+
const declaredHooks = new Map((validated.contributes?.hooks ?? []).map((h) => [h.id, h]));
|
|
47
|
+
for (const hookId of Object.keys(runtime.hooks ?? {})) {
|
|
48
|
+
const metadata = declaredHooks.get(hookId);
|
|
49
|
+
if (!metadata) {
|
|
50
|
+
throw new Error(`definePlugin(${validated.name}): typed hook "${hookId}" has no matching metadata entry in contributes.hooks`);
|
|
51
|
+
}
|
|
52
|
+
if (metadata.command) {
|
|
53
|
+
throw new Error(`definePlugin(${validated.name}): hook "${hookId}" has both a typed implementation and a command string \u2014 pick one`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (runtime.hooks) {
|
|
57
|
+
for (const h of declaredHooks.values()) {
|
|
58
|
+
if (!runtime.hooks[h.id] && !h.command) {
|
|
59
|
+
throw new Error(`definePlugin(${validated.name}): hook metadata "${h.id}" has no implementation (typed function or command)`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const declaredCapabilities = new Map((validated.contributes?.capabilities ?? []).map((capability) => [capability.id, capability]));
|
|
64
|
+
for (const capability of runtime.featureCapabilities ?? []) {
|
|
65
|
+
if (!declaredCapabilities.has(capability.id)) {
|
|
66
|
+
throw new Error(`definePlugin(${validated.name}): executable capability "${capability.id}" has no matching metadata entry in contributes.capabilities`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const declaredPanels = new Map((validated.contributes?.panels ?? []).map((panel) => [panel.id, panel]));
|
|
70
|
+
for (const panel of runtime.panels ?? []) {
|
|
71
|
+
const metadata = declaredPanels.get(panel.id);
|
|
72
|
+
if (!metadata) {
|
|
73
|
+
throw new Error(`definePlugin(${validated.name}): executable panel "${panel.id}" has no matching metadata entry in contributes.panels`);
|
|
74
|
+
}
|
|
75
|
+
if (metadata.slot !== panel.slot) {
|
|
76
|
+
throw new Error(`definePlugin(${validated.name}): executable panel "${panel.id}" slot "${panel.slot}" does not match metadata slot "${metadata.slot}"`);
|
|
77
|
+
}
|
|
78
|
+
if (metadata.capabilityId !== panel.capabilityId) {
|
|
79
|
+
throw new Error(`definePlugin(${validated.name}): executable panel "${panel.id}" capabilityId "${panel.capabilityId ?? "(none)"}" does not match metadata capabilityId "${metadata.capabilityId ?? "(none)"}"`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const declaredBlockerClassifiers = new Map((validated.contributes?.blockerClassifiers ?? []).map((classifier) => [classifier.id, classifier]));
|
|
83
|
+
for (const classifier of runtime.blockerClassifiers ?? []) {
|
|
84
|
+
if (!declaredBlockerClassifiers.has(classifier.id)) {
|
|
85
|
+
throw new Error(`definePlugin(${validated.name}): executable blocker classifier "${classifier.id}" has no matching metadata entry in contributes.blockerClassifiers`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const declaredCliCommands = new Map((validated.contributes?.cliCommands ?? []).map((command) => [command.id, command]));
|
|
89
|
+
for (const command of runtime.cliCommands ?? []) {
|
|
90
|
+
if (!declaredCliCommands.has(command.id)) {
|
|
91
|
+
throw new Error(`definePlugin(${validated.name}): executable cli command "${command.id}" has no matching metadata entry in contributes.cliCommands`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
46
94
|
return { ...validated, __runtime: runtime };
|
|
47
95
|
}
|
|
48
96
|
export {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { DependencyEdge as ContractDependencyEdge, DependencyNode as ContractDependencyNode, EngineReadModel, TaskSummary } from "@rig/contracts";
|
|
2
|
+
import { type TaskGraphLayout } from "./taskGraphLayout";
|
|
3
|
+
export type DependencyEdgeType = ContractDependencyEdge["type"];
|
|
4
|
+
export interface DependencyEdge {
|
|
5
|
+
readonly fromTaskId: string;
|
|
6
|
+
readonly toTaskId: string;
|
|
7
|
+
readonly type: DependencyEdgeType;
|
|
8
|
+
}
|
|
9
|
+
export interface DependencyNode {
|
|
10
|
+
readonly taskId: string;
|
|
11
|
+
readonly title: string;
|
|
12
|
+
readonly status: ContractDependencyNode["status"];
|
|
13
|
+
readonly priority: ContractDependencyNode["priority"];
|
|
14
|
+
readonly assignee: string | null;
|
|
15
|
+
readonly blockedBy: readonly string[];
|
|
16
|
+
readonly blocks: readonly string[];
|
|
17
|
+
readonly blockingDepth: number;
|
|
18
|
+
readonly blockerClass: null;
|
|
19
|
+
readonly actionRiskTier: null;
|
|
20
|
+
readonly epicKey: string | null;
|
|
21
|
+
readonly groupKey?: string | null;
|
|
22
|
+
readonly externalId?: string | null;
|
|
23
|
+
readonly sourceIssueId?: string | null;
|
|
24
|
+
readonly scope?: readonly string[];
|
|
25
|
+
readonly validationKeys?: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
export interface DependencyGraphModel {
|
|
28
|
+
readonly graphId: string;
|
|
29
|
+
readonly nodes: readonly DependencyNode[];
|
|
30
|
+
readonly edges: readonly DependencyEdge[];
|
|
31
|
+
readonly layout: TaskGraphLayout;
|
|
32
|
+
readonly cycles: readonly (readonly string[])[];
|
|
33
|
+
readonly unresolvedRefs: readonly string[];
|
|
34
|
+
readonly degraded: boolean;
|
|
35
|
+
readonly generatedAt: string;
|
|
36
|
+
}
|
|
37
|
+
export interface BuildDependencyGraphModelOptions {
|
|
38
|
+
readonly snapshot?: EngineReadModel | null;
|
|
39
|
+
readonly generatedAt?: string;
|
|
40
|
+
readonly graphId?: string;
|
|
41
|
+
readonly showParentChild?: boolean;
|
|
42
|
+
}
|
|
43
|
+
export declare function buildDependencyGraphModel(tasks: readonly TaskSummary[], options?: BuildDependencyGraphModelOptions): DependencyGraphModel;
|