@h-rig/planning-plugin 0.0.6-alpha.135 → 0.0.6-alpha.137
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/cli.d.ts +19 -0
- package/dist/src/cli.js +125 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +125 -8
- package/dist/src/plugin.d.ts +2 -0
- package/dist/src/plugin.js +141 -8
- package/package.json +4 -3
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RuntimeCliContext } from "@rig/core";
|
|
2
|
+
export declare const PLANNING_PLAN_CLI_ID = "planning.plan";
|
|
3
|
+
type CommandOutcome = {
|
|
4
|
+
readonly ok: boolean;
|
|
5
|
+
readonly group: string;
|
|
6
|
+
readonly command: string;
|
|
7
|
+
readonly details?: Record<string, unknown>;
|
|
8
|
+
};
|
|
9
|
+
export declare function executePlan(context: RuntimeCliContext, args: readonly string[]): Promise<CommandOutcome>;
|
|
10
|
+
export declare const planningCliCommands: readonly [{
|
|
11
|
+
readonly id: "planning.plan";
|
|
12
|
+
readonly family: "plan";
|
|
13
|
+
readonly command: "rig plan --text <prd>|--prd <file>";
|
|
14
|
+
readonly description: "Generate a plan from a PRD and optionally materialize task-source tasks.";
|
|
15
|
+
readonly usage: "rig plan --text <prd>|--prd <file> [--title <title>] [--materialize|--dry-run] [--json]";
|
|
16
|
+
readonly projectRequired: true;
|
|
17
|
+
readonly run: typeof executePlan;
|
|
18
|
+
}];
|
|
19
|
+
export {};
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/planning-plugin/src/cli.ts
|
|
3
|
+
import { readFileSync } from "fs";
|
|
4
|
+
import { createTask, planWorkspace } from "@rig/client";
|
|
5
|
+
|
|
6
|
+
// packages/planning-plugin/src/planning.ts
|
|
7
|
+
async function spec(input, ports) {
|
|
8
|
+
return ports.spec(input);
|
|
9
|
+
}
|
|
10
|
+
async function clarify(planSpec, context, ports) {
|
|
11
|
+
return ports.clarify(planSpec, context);
|
|
12
|
+
}
|
|
13
|
+
async function plan(planSpec, ports) {
|
|
14
|
+
return ports.plan(planSpec);
|
|
15
|
+
}
|
|
16
|
+
async function specClarifyPlan(input, context, ports) {
|
|
17
|
+
return plan(await clarify(await spec(input, ports), context, ports), ports);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// packages/planning-plugin/src/cli.ts
|
|
21
|
+
var PLANNING_PLAN_CLI_ID = "planning.plan";
|
|
22
|
+
function printJson(value) {
|
|
23
|
+
console.log(JSON.stringify(value, null, 2));
|
|
24
|
+
}
|
|
25
|
+
function takeFlag(args, flag) {
|
|
26
|
+
const rest = [...args];
|
|
27
|
+
const index = rest.indexOf(flag);
|
|
28
|
+
if (index < 0)
|
|
29
|
+
return { value: false, rest };
|
|
30
|
+
rest.splice(index, 1);
|
|
31
|
+
return { value: true, rest };
|
|
32
|
+
}
|
|
33
|
+
function takeOption(args, flag) {
|
|
34
|
+
const rest = [...args];
|
|
35
|
+
const index = rest.indexOf(flag);
|
|
36
|
+
if (index < 0)
|
|
37
|
+
return { rest };
|
|
38
|
+
const value = rest[index + 1];
|
|
39
|
+
if (!value || value.startsWith("-"))
|
|
40
|
+
throw new Error(`${flag} requires a value.`);
|
|
41
|
+
rest.splice(index, 2);
|
|
42
|
+
return { value, rest };
|
|
43
|
+
}
|
|
44
|
+
function requireNoExtraArgs(args, usage) {
|
|
45
|
+
if (args.length > 0)
|
|
46
|
+
throw new Error(`Unexpected argument: ${args[0]}
|
|
47
|
+
Usage: ${usage}`);
|
|
48
|
+
}
|
|
49
|
+
function defaultPlanningProvider(now) {
|
|
50
|
+
return {
|
|
51
|
+
spec: (input) => {
|
|
52
|
+
const headings = input.body.split(/\r?\n/).map((line) => line.match(/^#{1,3}\s+(.+)$/)?.[1]?.trim()).filter((line) => Boolean(line));
|
|
53
|
+
const titles = headings.length > 0 ? headings : [input.title];
|
|
54
|
+
return {
|
|
55
|
+
prdTitle: input.title,
|
|
56
|
+
userStories: [],
|
|
57
|
+
functionalRequirements: [],
|
|
58
|
+
openQuestions: [],
|
|
59
|
+
tasks: titles.map((title, index) => ({
|
|
60
|
+
localId: `task-${index + 1}`,
|
|
61
|
+
title,
|
|
62
|
+
description: `Implement: ${title}`,
|
|
63
|
+
acceptance: [],
|
|
64
|
+
scope: [],
|
|
65
|
+
validationKeys: [],
|
|
66
|
+
dependsOn: index === 0 ? [] : [`task-${index}`],
|
|
67
|
+
parent: null,
|
|
68
|
+
parallelizable: index === 0
|
|
69
|
+
})),
|
|
70
|
+
generatedAt: now()
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
clarify: (planSpec) => planSpec,
|
|
74
|
+
plan: (planSpec) => planSpec
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function readPrdText(args) {
|
|
78
|
+
const title = takeOption(args, "--title");
|
|
79
|
+
const text = takeOption(title.rest, "--text");
|
|
80
|
+
const prd = takeOption(text.rest, "--prd");
|
|
81
|
+
const body = text.value ?? (prd.value ? readFileSync(prd.value, "utf8") : null);
|
|
82
|
+
if (!body?.trim())
|
|
83
|
+
throw new Error("rig plan requires --text <prd> or --prd <file>.");
|
|
84
|
+
return { title: title.value?.trim() || "Rig generated plan", body, rest: prd.rest };
|
|
85
|
+
}
|
|
86
|
+
async function executePlan(context, args) {
|
|
87
|
+
const materialize = takeFlag(args, "--materialize");
|
|
88
|
+
const dryRun = takeFlag(materialize.rest, "--dry-run");
|
|
89
|
+
const json = takeFlag(dryRun.rest, "--json");
|
|
90
|
+
if (materialize.value && dryRun.value)
|
|
91
|
+
throw new Error("Pass only one of --materialize or --dry-run.");
|
|
92
|
+
const prd = readPrdText(json.rest);
|
|
93
|
+
requireNoExtraArgs(prd.rest, "rig plan --text <prd>|--prd <file> [--title <title>] [--materialize|--dry-run] [--json]");
|
|
94
|
+
const willMaterialize = materialize.value && !dryRun.value;
|
|
95
|
+
const now = () => new Date().toISOString();
|
|
96
|
+
const provider = defaultPlanningProvider(now);
|
|
97
|
+
const result = await planWorkspace(context.projectRoot, prd.body, {
|
|
98
|
+
generatePlan: (input) => specClarifyPlan({ title: input.title ?? prd.title, body: input.prd }, {}, provider),
|
|
99
|
+
createTask
|
|
100
|
+
}, { title: prd.title, materialize: willMaterialize });
|
|
101
|
+
if (context.outputMode === "text") {
|
|
102
|
+
if (json.value)
|
|
103
|
+
printJson(result);
|
|
104
|
+
else
|
|
105
|
+
console.log(result.spec.tasks.map((task) => `${task.localId} ${task.title}`).join(`
|
|
106
|
+
`) || "No plan tasks.");
|
|
107
|
+
}
|
|
108
|
+
return { ok: true, group: "plan", command: willMaterialize ? "materialize" : "show", details: result };
|
|
109
|
+
}
|
|
110
|
+
var planningCliCommands = [
|
|
111
|
+
{
|
|
112
|
+
id: PLANNING_PLAN_CLI_ID,
|
|
113
|
+
family: "plan",
|
|
114
|
+
command: "rig plan --text <prd>|--prd <file>",
|
|
115
|
+
description: "Generate a plan from a PRD and optionally materialize task-source tasks.",
|
|
116
|
+
usage: "rig plan --text <prd>|--prd <file> [--title <title>] [--materialize|--dry-run] [--json]",
|
|
117
|
+
projectRequired: true,
|
|
118
|
+
run: executePlan
|
|
119
|
+
}
|
|
120
|
+
];
|
|
121
|
+
export {
|
|
122
|
+
planningCliCommands,
|
|
123
|
+
executePlan,
|
|
124
|
+
PLANNING_PLAN_CLI_ID
|
|
125
|
+
};
|
package/dist/src/index.d.ts
CHANGED
package/dist/src/index.js
CHANGED
|
@@ -115,30 +115,147 @@ async function materialize(planSpec, source, options = {}) {
|
|
|
115
115
|
}
|
|
116
116
|
return { planId, created, existing, localIdToTaskId: Object.fromEntries(localIdToTaskId) };
|
|
117
117
|
}
|
|
118
|
+
// packages/planning-plugin/src/cli.ts
|
|
119
|
+
import { readFileSync } from "fs";
|
|
120
|
+
import { createTask, planWorkspace } from "@rig/client";
|
|
121
|
+
var PLANNING_PLAN_CLI_ID = "planning.plan";
|
|
122
|
+
function printJson(value) {
|
|
123
|
+
console.log(JSON.stringify(value, null, 2));
|
|
124
|
+
}
|
|
125
|
+
function takeFlag(args, flag) {
|
|
126
|
+
const rest = [...args];
|
|
127
|
+
const index = rest.indexOf(flag);
|
|
128
|
+
if (index < 0)
|
|
129
|
+
return { value: false, rest };
|
|
130
|
+
rest.splice(index, 1);
|
|
131
|
+
return { value: true, rest };
|
|
132
|
+
}
|
|
133
|
+
function takeOption(args, flag) {
|
|
134
|
+
const rest = [...args];
|
|
135
|
+
const index = rest.indexOf(flag);
|
|
136
|
+
if (index < 0)
|
|
137
|
+
return { rest };
|
|
138
|
+
const value = rest[index + 1];
|
|
139
|
+
if (!value || value.startsWith("-"))
|
|
140
|
+
throw new Error(`${flag} requires a value.`);
|
|
141
|
+
rest.splice(index, 2);
|
|
142
|
+
return { value, rest };
|
|
143
|
+
}
|
|
144
|
+
function requireNoExtraArgs(args, usage) {
|
|
145
|
+
if (args.length > 0)
|
|
146
|
+
throw new Error(`Unexpected argument: ${args[0]}
|
|
147
|
+
Usage: ${usage}`);
|
|
148
|
+
}
|
|
149
|
+
function defaultPlanningProvider(now) {
|
|
150
|
+
return {
|
|
151
|
+
spec: (input) => {
|
|
152
|
+
const headings = input.body.split(/\r?\n/).map((line) => line.match(/^#{1,3}\s+(.+)$/)?.[1]?.trim()).filter((line) => Boolean(line));
|
|
153
|
+
const titles = headings.length > 0 ? headings : [input.title];
|
|
154
|
+
return {
|
|
155
|
+
prdTitle: input.title,
|
|
156
|
+
userStories: [],
|
|
157
|
+
functionalRequirements: [],
|
|
158
|
+
openQuestions: [],
|
|
159
|
+
tasks: titles.map((title, index) => ({
|
|
160
|
+
localId: `task-${index + 1}`,
|
|
161
|
+
title,
|
|
162
|
+
description: `Implement: ${title}`,
|
|
163
|
+
acceptance: [],
|
|
164
|
+
scope: [],
|
|
165
|
+
validationKeys: [],
|
|
166
|
+
dependsOn: index === 0 ? [] : [`task-${index}`],
|
|
167
|
+
parent: null,
|
|
168
|
+
parallelizable: index === 0
|
|
169
|
+
})),
|
|
170
|
+
generatedAt: now()
|
|
171
|
+
};
|
|
172
|
+
},
|
|
173
|
+
clarify: (planSpec) => planSpec,
|
|
174
|
+
plan: (planSpec) => planSpec
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function readPrdText(args) {
|
|
178
|
+
const title = takeOption(args, "--title");
|
|
179
|
+
const text = takeOption(title.rest, "--text");
|
|
180
|
+
const prd = takeOption(text.rest, "--prd");
|
|
181
|
+
const body = text.value ?? (prd.value ? readFileSync(prd.value, "utf8") : null);
|
|
182
|
+
if (!body?.trim())
|
|
183
|
+
throw new Error("rig plan requires --text <prd> or --prd <file>.");
|
|
184
|
+
return { title: title.value?.trim() || "Rig generated plan", body, rest: prd.rest };
|
|
185
|
+
}
|
|
186
|
+
async function executePlan(context, args) {
|
|
187
|
+
const materialize2 = takeFlag(args, "--materialize");
|
|
188
|
+
const dryRun = takeFlag(materialize2.rest, "--dry-run");
|
|
189
|
+
const json = takeFlag(dryRun.rest, "--json");
|
|
190
|
+
if (materialize2.value && dryRun.value)
|
|
191
|
+
throw new Error("Pass only one of --materialize or --dry-run.");
|
|
192
|
+
const prd = readPrdText(json.rest);
|
|
193
|
+
requireNoExtraArgs(prd.rest, "rig plan --text <prd>|--prd <file> [--title <title>] [--materialize|--dry-run] [--json]");
|
|
194
|
+
const willMaterialize = materialize2.value && !dryRun.value;
|
|
195
|
+
const now = () => new Date().toISOString();
|
|
196
|
+
const provider = defaultPlanningProvider(now);
|
|
197
|
+
const result = await planWorkspace(context.projectRoot, prd.body, {
|
|
198
|
+
generatePlan: (input) => specClarifyPlan({ title: input.title ?? prd.title, body: input.prd }, {}, provider),
|
|
199
|
+
createTask
|
|
200
|
+
}, { title: prd.title, materialize: willMaterialize });
|
|
201
|
+
if (context.outputMode === "text") {
|
|
202
|
+
if (json.value)
|
|
203
|
+
printJson(result);
|
|
204
|
+
else
|
|
205
|
+
console.log(result.spec.tasks.map((task) => `${task.localId} ${task.title}`).join(`
|
|
206
|
+
`) || "No plan tasks.");
|
|
207
|
+
}
|
|
208
|
+
return { ok: true, group: "plan", command: willMaterialize ? "materialize" : "show", details: result };
|
|
209
|
+
}
|
|
210
|
+
var planningCliCommands = [
|
|
211
|
+
{
|
|
212
|
+
id: PLANNING_PLAN_CLI_ID,
|
|
213
|
+
family: "plan",
|
|
214
|
+
command: "rig plan --text <prd>|--prd <file>",
|
|
215
|
+
description: "Generate a plan from a PRD and optionally materialize task-source tasks.",
|
|
216
|
+
usage: "rig plan --text <prd>|--prd <file> [--title <title>] [--materialize|--dry-run] [--json]",
|
|
217
|
+
projectRequired: true,
|
|
218
|
+
run: executePlan
|
|
219
|
+
}
|
|
220
|
+
];
|
|
118
221
|
// packages/planning-plugin/src/plugin.ts
|
|
119
222
|
import { definePlugin } from "@rig/core";
|
|
120
223
|
var PLANNING_PLUGIN_NAME = "@rig/planning-plugin";
|
|
224
|
+
var PLANNING_PLAN_PANEL_ID = "plan-intake";
|
|
121
225
|
var planningPlugin = definePlugin({
|
|
122
226
|
name: PLANNING_PLUGIN_NAME,
|
|
123
227
|
version: "0.0.0-alpha.1",
|
|
124
228
|
provides: [],
|
|
125
229
|
requires: [],
|
|
126
230
|
contributes: {
|
|
127
|
-
|
|
128
|
-
{
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
231
|
+
capabilities: [
|
|
232
|
+
{ id: "planning.plan", title: "PRD-to-task planning", commandId: PLANNING_PLAN_CLI_ID, panelId: PLANNING_PLAN_PANEL_ID }
|
|
233
|
+
],
|
|
234
|
+
panels: [
|
|
235
|
+
{ id: PLANNING_PLAN_PANEL_ID, slot: "capability", title: "Plan intake", capabilityId: "planning.plan" }
|
|
236
|
+
],
|
|
237
|
+
cliCommands: planningCliCommands.map(({ run: _run, ...metadata }) => metadata)
|
|
134
238
|
}
|
|
239
|
+
}, {
|
|
240
|
+
featureCapabilities: [
|
|
241
|
+
{ id: "planning.plan", title: "PRD-to-task planning", commandId: PLANNING_PLAN_CLI_ID, panelId: PLANNING_PLAN_PANEL_ID }
|
|
242
|
+
],
|
|
243
|
+
cliCommands: planningCliCommands
|
|
135
244
|
});
|
|
245
|
+
function createPlanningPlugin() {
|
|
246
|
+
return planningPlugin;
|
|
247
|
+
}
|
|
136
248
|
export {
|
|
137
249
|
specClarifyPlan,
|
|
138
250
|
spec,
|
|
139
251
|
planningPlugin,
|
|
252
|
+
planningCliCommands,
|
|
140
253
|
plan,
|
|
141
254
|
materialize,
|
|
255
|
+
executePlan,
|
|
256
|
+
createPlanningPlugin,
|
|
142
257
|
clarify,
|
|
143
|
-
PLANNING_PLUGIN_NAME
|
|
258
|
+
PLANNING_PLUGIN_NAME,
|
|
259
|
+
PLANNING_PLAN_PANEL_ID,
|
|
260
|
+
PLANNING_PLAN_CLI_ID
|
|
144
261
|
};
|
package/dist/src/plugin.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export declare const PLANNING_PLUGIN_NAME = "@rig/planning-plugin";
|
|
2
|
+
export declare const PLANNING_PLAN_PANEL_ID = "plan-intake";
|
|
2
3
|
export declare const planningPlugin: import("@rig/core").RigPluginWithRuntime;
|
|
4
|
+
export declare function createPlanningPlugin(): import("@rig/core").RigPluginWithRuntime;
|
|
3
5
|
export default planningPlugin;
|
package/dist/src/plugin.js
CHANGED
|
@@ -1,25 +1,158 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/planning-plugin/src/plugin.ts
|
|
3
3
|
import { definePlugin } from "@rig/core";
|
|
4
|
+
|
|
5
|
+
// packages/planning-plugin/src/cli.ts
|
|
6
|
+
import { readFileSync } from "fs";
|
|
7
|
+
import { createTask, planWorkspace } from "@rig/client";
|
|
8
|
+
|
|
9
|
+
// packages/planning-plugin/src/planning.ts
|
|
10
|
+
async function spec(input, ports) {
|
|
11
|
+
return ports.spec(input);
|
|
12
|
+
}
|
|
13
|
+
async function clarify(planSpec, context, ports) {
|
|
14
|
+
return ports.clarify(planSpec, context);
|
|
15
|
+
}
|
|
16
|
+
async function plan(planSpec, ports) {
|
|
17
|
+
return ports.plan(planSpec);
|
|
18
|
+
}
|
|
19
|
+
async function specClarifyPlan(input, context, ports) {
|
|
20
|
+
return plan(await clarify(await spec(input, ports), context, ports), ports);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// packages/planning-plugin/src/cli.ts
|
|
24
|
+
var PLANNING_PLAN_CLI_ID = "planning.plan";
|
|
25
|
+
function printJson(value) {
|
|
26
|
+
console.log(JSON.stringify(value, null, 2));
|
|
27
|
+
}
|
|
28
|
+
function takeFlag(args, flag) {
|
|
29
|
+
const rest = [...args];
|
|
30
|
+
const index = rest.indexOf(flag);
|
|
31
|
+
if (index < 0)
|
|
32
|
+
return { value: false, rest };
|
|
33
|
+
rest.splice(index, 1);
|
|
34
|
+
return { value: true, rest };
|
|
35
|
+
}
|
|
36
|
+
function takeOption(args, flag) {
|
|
37
|
+
const rest = [...args];
|
|
38
|
+
const index = rest.indexOf(flag);
|
|
39
|
+
if (index < 0)
|
|
40
|
+
return { rest };
|
|
41
|
+
const value = rest[index + 1];
|
|
42
|
+
if (!value || value.startsWith("-"))
|
|
43
|
+
throw new Error(`${flag} requires a value.`);
|
|
44
|
+
rest.splice(index, 2);
|
|
45
|
+
return { value, rest };
|
|
46
|
+
}
|
|
47
|
+
function requireNoExtraArgs(args, usage) {
|
|
48
|
+
if (args.length > 0)
|
|
49
|
+
throw new Error(`Unexpected argument: ${args[0]}
|
|
50
|
+
Usage: ${usage}`);
|
|
51
|
+
}
|
|
52
|
+
function defaultPlanningProvider(now) {
|
|
53
|
+
return {
|
|
54
|
+
spec: (input) => {
|
|
55
|
+
const headings = input.body.split(/\r?\n/).map((line) => line.match(/^#{1,3}\s+(.+)$/)?.[1]?.trim()).filter((line) => Boolean(line));
|
|
56
|
+
const titles = headings.length > 0 ? headings : [input.title];
|
|
57
|
+
return {
|
|
58
|
+
prdTitle: input.title,
|
|
59
|
+
userStories: [],
|
|
60
|
+
functionalRequirements: [],
|
|
61
|
+
openQuestions: [],
|
|
62
|
+
tasks: titles.map((title, index) => ({
|
|
63
|
+
localId: `task-${index + 1}`,
|
|
64
|
+
title,
|
|
65
|
+
description: `Implement: ${title}`,
|
|
66
|
+
acceptance: [],
|
|
67
|
+
scope: [],
|
|
68
|
+
validationKeys: [],
|
|
69
|
+
dependsOn: index === 0 ? [] : [`task-${index}`],
|
|
70
|
+
parent: null,
|
|
71
|
+
parallelizable: index === 0
|
|
72
|
+
})),
|
|
73
|
+
generatedAt: now()
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
clarify: (planSpec) => planSpec,
|
|
77
|
+
plan: (planSpec) => planSpec
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function readPrdText(args) {
|
|
81
|
+
const title = takeOption(args, "--title");
|
|
82
|
+
const text = takeOption(title.rest, "--text");
|
|
83
|
+
const prd = takeOption(text.rest, "--prd");
|
|
84
|
+
const body = text.value ?? (prd.value ? readFileSync(prd.value, "utf8") : null);
|
|
85
|
+
if (!body?.trim())
|
|
86
|
+
throw new Error("rig plan requires --text <prd> or --prd <file>.");
|
|
87
|
+
return { title: title.value?.trim() || "Rig generated plan", body, rest: prd.rest };
|
|
88
|
+
}
|
|
89
|
+
async function executePlan(context, args) {
|
|
90
|
+
const materialize = takeFlag(args, "--materialize");
|
|
91
|
+
const dryRun = takeFlag(materialize.rest, "--dry-run");
|
|
92
|
+
const json = takeFlag(dryRun.rest, "--json");
|
|
93
|
+
if (materialize.value && dryRun.value)
|
|
94
|
+
throw new Error("Pass only one of --materialize or --dry-run.");
|
|
95
|
+
const prd = readPrdText(json.rest);
|
|
96
|
+
requireNoExtraArgs(prd.rest, "rig plan --text <prd>|--prd <file> [--title <title>] [--materialize|--dry-run] [--json]");
|
|
97
|
+
const willMaterialize = materialize.value && !dryRun.value;
|
|
98
|
+
const now = () => new Date().toISOString();
|
|
99
|
+
const provider = defaultPlanningProvider(now);
|
|
100
|
+
const result = await planWorkspace(context.projectRoot, prd.body, {
|
|
101
|
+
generatePlan: (input) => specClarifyPlan({ title: input.title ?? prd.title, body: input.prd }, {}, provider),
|
|
102
|
+
createTask
|
|
103
|
+
}, { title: prd.title, materialize: willMaterialize });
|
|
104
|
+
if (context.outputMode === "text") {
|
|
105
|
+
if (json.value)
|
|
106
|
+
printJson(result);
|
|
107
|
+
else
|
|
108
|
+
console.log(result.spec.tasks.map((task) => `${task.localId} ${task.title}`).join(`
|
|
109
|
+
`) || "No plan tasks.");
|
|
110
|
+
}
|
|
111
|
+
return { ok: true, group: "plan", command: willMaterialize ? "materialize" : "show", details: result };
|
|
112
|
+
}
|
|
113
|
+
var planningCliCommands = [
|
|
114
|
+
{
|
|
115
|
+
id: PLANNING_PLAN_CLI_ID,
|
|
116
|
+
family: "plan",
|
|
117
|
+
command: "rig plan --text <prd>|--prd <file>",
|
|
118
|
+
description: "Generate a plan from a PRD and optionally materialize task-source tasks.",
|
|
119
|
+
usage: "rig plan --text <prd>|--prd <file> [--title <title>] [--materialize|--dry-run] [--json]",
|
|
120
|
+
projectRequired: true,
|
|
121
|
+
run: executePlan
|
|
122
|
+
}
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
// packages/planning-plugin/src/plugin.ts
|
|
4
126
|
var PLANNING_PLUGIN_NAME = "@rig/planning-plugin";
|
|
127
|
+
var PLANNING_PLAN_PANEL_ID = "plan-intake";
|
|
5
128
|
var planningPlugin = definePlugin({
|
|
6
129
|
name: PLANNING_PLUGIN_NAME,
|
|
7
130
|
version: "0.0.0-alpha.1",
|
|
8
131
|
provides: [],
|
|
9
132
|
requires: [],
|
|
10
133
|
contributes: {
|
|
11
|
-
|
|
12
|
-
{
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
134
|
+
capabilities: [
|
|
135
|
+
{ id: "planning.plan", title: "PRD-to-task planning", commandId: PLANNING_PLAN_CLI_ID, panelId: PLANNING_PLAN_PANEL_ID }
|
|
136
|
+
],
|
|
137
|
+
panels: [
|
|
138
|
+
{ id: PLANNING_PLAN_PANEL_ID, slot: "capability", title: "Plan intake", capabilityId: "planning.plan" }
|
|
139
|
+
],
|
|
140
|
+
cliCommands: planningCliCommands.map(({ run: _run, ...metadata }) => metadata)
|
|
18
141
|
}
|
|
142
|
+
}, {
|
|
143
|
+
featureCapabilities: [
|
|
144
|
+
{ id: "planning.plan", title: "PRD-to-task planning", commandId: PLANNING_PLAN_CLI_ID, panelId: PLANNING_PLAN_PANEL_ID }
|
|
145
|
+
],
|
|
146
|
+
cliCommands: planningCliCommands
|
|
19
147
|
});
|
|
148
|
+
function createPlanningPlugin() {
|
|
149
|
+
return planningPlugin;
|
|
150
|
+
}
|
|
20
151
|
var plugin_default = planningPlugin;
|
|
21
152
|
export {
|
|
22
153
|
planningPlugin,
|
|
23
154
|
plugin_default as default,
|
|
24
|
-
|
|
155
|
+
createPlanningPlugin,
|
|
156
|
+
PLANNING_PLUGIN_NAME,
|
|
157
|
+
PLANNING_PLAN_PANEL_ID
|
|
25
158
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h-rig/planning-plugin",
|
|
3
|
-
"version": "0.0.6-alpha.
|
|
3
|
+
"version": "0.0.6-alpha.137",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "First-party PRD-to-plan plugin for Rig task sources.",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"module": "./dist/src/index.js",
|
|
30
30
|
"types": "./dist/src/index.d.ts",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@rig/
|
|
33
|
-
"@rig/
|
|
32
|
+
"@rig/client": "npm:@h-rig/client@0.0.6-alpha.137",
|
|
33
|
+
"@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.137",
|
|
34
|
+
"@rig/core": "npm:@h-rig/core@0.0.6-alpha.137"
|
|
34
35
|
}
|
|
35
36
|
}
|