@slope-dev/slope 1.58.5 → 1.59.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/README.md +21 -0
- package/dist/cli/commands/help.d.ts +3 -1
- package/dist/cli/commands/help.d.ts.map +1 -1
- package/dist/cli/commands/help.js +60 -12
- package/dist/cli/commands/help.js.map +1 -1
- package/dist/cli/commands/now.d.ts +30 -0
- package/dist/cli/commands/now.d.ts.map +1 -0
- package/dist/cli/commands/now.js +155 -0
- package/dist/cli/commands/now.js.map +1 -0
- package/dist/cli/commands/roadmap.d.ts.map +1 -1
- package/dist/cli/commands/roadmap.js +129 -1
- package/dist/cli/commands/roadmap.js.map +1 -1
- package/dist/cli/commands/start.d.ts +2 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +57 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.d.ts +5 -0
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +21 -3
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/index.js +17 -126
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/registry.d.ts +3 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cli/registry.js +83 -60
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli/template-generator.d.ts.map +1 -1
- package/dist/cli/template-generator.js +58 -24
- package/dist/cli/template-generator.js.map +1 -1
- package/dist/core/adapters/generic.d.ts.map +1 -1
- package/dist/core/adapters/generic.js +5 -0
- package/dist/core/adapters/generic.js.map +1 -1
- package/dist/core/analyzers/git.d.ts.map +1 -1
- package/dist/core/analyzers/git.js +10 -1
- package/dist/core/analyzers/git.js.map +1 -1
- package/dist/mcp/index.js +1 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/registry.js +2 -2
- package/dist/mcp/registry.js.map +1 -1
- package/package.json +1 -1
- package/packages/pi-extension/dist/index.js +5 -4
- package/templates/codex/plugins/slope/.codex-plugin/plugin.json +1 -1
- package/templates/codex/plugins/slope/skills/slope-setup/SKILL.md +4 -0
- package/templates/codex/plugins/slope/skills/slope-sprint/SKILL.md +1 -0
package/README.md
CHANGED
|
@@ -176,6 +176,7 @@ Install and initialize SLOPE for this project. Run these commands:
|
|
|
176
176
|
2. npx slope map
|
|
177
177
|
|
|
178
178
|
This will create opencode.json, .opencode/plugins/, AGENTS.md, and CODEBASE.md.
|
|
179
|
+
For roadmap planning intake, run `npx slope roadmap interview --agent` or ask the MCP server for `search({ module: "init" })`.
|
|
179
180
|
```
|
|
180
181
|
|
|
181
182
|
**What you get:**
|
|
@@ -261,6 +262,20 @@ execute({ code: 'return computeHandicapCard(loadScorecards())' })
|
|
|
261
262
|
|
|
262
263
|
All commands use `npx slope` when installed locally.
|
|
263
264
|
|
|
265
|
+
Default help is intentionally small:
|
|
266
|
+
|
|
267
|
+
| Command | Description |
|
|
268
|
+
|---------|-------------|
|
|
269
|
+
| `npx slope now` | Compact current-state cockpit: current sprint, state, claims, next action |
|
|
270
|
+
| `npx slope start [--ticket=KEY]` | Start or begin work without exposing sprint/claim plumbing |
|
|
271
|
+
| `npx slope help` | Human command surface for daily work, setup, and direction |
|
|
272
|
+
| `npx slope help <command>` | Detailed usage for one command |
|
|
273
|
+
| `npx slope help --all` | Full command registry with audience labels |
|
|
274
|
+
|
|
275
|
+
Commands are classified as `human`, `agent`, `advanced`, or `internal`.
|
|
276
|
+
Humans should usually start with the default help surface; skills and agents
|
|
277
|
+
orchestrate the rest of the CLI as execution primitives.
|
|
278
|
+
|
|
264
279
|
### Setup
|
|
265
280
|
|
|
266
281
|
| Command | Description |
|
|
@@ -285,10 +300,16 @@ All commands use `npx slope` when installed locally.
|
|
|
285
300
|
|
|
286
301
|
| Command | Description |
|
|
287
302
|
|---------|-------------|
|
|
303
|
+
| `npx slope now` | Compact current-state cockpit |
|
|
304
|
+
| `npx slope start [--ticket=KEY]` | Start sprint state or begin a ticket with briefing, claim, prep, and next gates |
|
|
288
305
|
| `npx slope briefing` | Pre-sprint hazard index, nutrition alerts, filtered gotchas |
|
|
289
306
|
| `npx slope plan --complexity=<level>` | Club recommendation + training plan |
|
|
290
307
|
| `npx slope next` | Show next sprint number |
|
|
308
|
+
| `npx slope roadmap interview` | Run the project interview when planning input is needed |
|
|
309
|
+
| `npx slope roadmap status [--sprint=N]` | Compact current roadmap state: active work, blockers, next ready, upcoming |
|
|
310
|
+
| `npx slope roadmap status --full` | Full historical roadmap status |
|
|
291
311
|
| `npx slope roadmap validate` | Validate roadmap dependencies and sprint status |
|
|
312
|
+
| `npx slope vision create` + `npx slope roadmap generate` | Create vision-backed roadmap plans from concrete backlog signals |
|
|
292
313
|
|
|
293
314
|
### Review & Findings
|
|
294
315
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* slope help [command]
|
|
2
|
+
* slope help [command] - Show human help, full registry, or command details.
|
|
3
3
|
*/
|
|
4
4
|
export declare function helpCommand(args: string[]): Promise<void>;
|
|
5
|
+
export declare function printDefaultHelp(): void;
|
|
6
|
+
export declare function printAllCommandHelp(): void;
|
|
5
7
|
//# sourceMappingURL=help.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/help.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/help.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgC/D;AAuBD,wBAAgB,gBAAgB,IAAI,IAAI,CAiBvC;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAgC1C"}
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
import { CLI_COMMAND_REGISTRY, CLI_INTERNAL_MODULES } from '../registry.js';
|
|
2
2
|
/**
|
|
3
|
-
* slope help [command]
|
|
3
|
+
* slope help [command] - Show human help, full registry, or command details.
|
|
4
4
|
*/
|
|
5
5
|
export async function helpCommand(args) {
|
|
6
6
|
if (args.includes('--help') || args.includes('-h')) {
|
|
7
7
|
console.log(`
|
|
8
|
-
slope help
|
|
8
|
+
slope help - Command reference
|
|
9
9
|
|
|
10
10
|
Usage:
|
|
11
|
-
slope help Show
|
|
11
|
+
slope help Show the bounded human command surface
|
|
12
12
|
slope help <command> Show detailed usage for a command
|
|
13
|
+
slope help --all Show all commands grouped by category
|
|
13
14
|
`);
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
+
if (args.includes('--all')) {
|
|
18
|
+
printAllCommandHelp();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const commandName = args.find(arg => !arg.startsWith('-'));
|
|
17
22
|
if (!commandName) {
|
|
18
|
-
|
|
23
|
+
printDefaultHelp();
|
|
19
24
|
return;
|
|
20
25
|
}
|
|
21
26
|
const meta = CLI_COMMAND_REGISTRY.find(c => c.cmd === commandName);
|
|
@@ -25,7 +30,44 @@ Usage:
|
|
|
25
30
|
}
|
|
26
31
|
printCommandDetail(meta);
|
|
27
32
|
}
|
|
28
|
-
|
|
33
|
+
const HUMAN_HELP_ORDER = [
|
|
34
|
+
'now',
|
|
35
|
+
'start',
|
|
36
|
+
'briefing',
|
|
37
|
+
'review',
|
|
38
|
+
'doctor',
|
|
39
|
+
'card',
|
|
40
|
+
'status',
|
|
41
|
+
'roadmap',
|
|
42
|
+
'vision',
|
|
43
|
+
'quickstart',
|
|
44
|
+
'init',
|
|
45
|
+
];
|
|
46
|
+
const AUDIENCE_LABELS = {
|
|
47
|
+
human: 'human',
|
|
48
|
+
agent: 'agent',
|
|
49
|
+
advanced: 'advanced',
|
|
50
|
+
internal: 'internal',
|
|
51
|
+
};
|
|
52
|
+
export function printDefaultHelp() {
|
|
53
|
+
const byName = new Map(CLI_COMMAND_REGISTRY.map(cmd => [cmd.cmd, cmd]));
|
|
54
|
+
console.log('\nSLOPE - Human Command Surface\n');
|
|
55
|
+
console.log('Daily work:');
|
|
56
|
+
for (const name of HUMAN_HELP_ORDER.slice(0, 8)) {
|
|
57
|
+
const cmd = byName.get(name);
|
|
58
|
+
if (cmd)
|
|
59
|
+
printCommandRow(cmd, 4);
|
|
60
|
+
}
|
|
61
|
+
console.log('\nSetup and direction:');
|
|
62
|
+
for (const name of HUMAN_HELP_ORDER.slice(8)) {
|
|
63
|
+
const cmd = byName.get(name);
|
|
64
|
+
if (cmd)
|
|
65
|
+
printCommandRow(cmd, 4);
|
|
66
|
+
}
|
|
67
|
+
console.log('\nAgents and skills use the rest of the CLI as execution primitives.');
|
|
68
|
+
console.log('Run `slope help <command>` for details, or `slope help --all` for the full registry.\n');
|
|
69
|
+
}
|
|
70
|
+
export function printAllCommandHelp() {
|
|
29
71
|
const categories = {};
|
|
30
72
|
for (const cmd of CLI_COMMAND_REGISTRY) {
|
|
31
73
|
if (CLI_INTERNAL_MODULES.includes(cmd.cmd))
|
|
@@ -35,7 +77,7 @@ function printCategoryList() {
|
|
|
35
77
|
categories[cat] = [];
|
|
36
78
|
categories[cat].push(cmd);
|
|
37
79
|
}
|
|
38
|
-
console.log('\nSLOPE CLI
|
|
80
|
+
console.log('\nSLOPE CLI - Full Command Reference\n');
|
|
39
81
|
const categoryOrder = ['lifecycle', 'scoring', 'analysis', 'planning', 'tooling'];
|
|
40
82
|
const categoryLabels = {
|
|
41
83
|
lifecycle: 'Lifecycle',
|
|
@@ -50,17 +92,17 @@ function printCategoryList() {
|
|
|
50
92
|
continue;
|
|
51
93
|
console.log(` ${categoryLabels[cat]}:`);
|
|
52
94
|
for (const cmd of cmds) {
|
|
53
|
-
|
|
54
|
-
console.log(` ${name.padEnd(18)} ${cmd.desc}`);
|
|
95
|
+
printCommandRow(cmd, 4, true);
|
|
55
96
|
}
|
|
56
97
|
console.log('');
|
|
57
98
|
}
|
|
58
|
-
console.log('Run `slope help <command>` for detailed usage.\n');
|
|
99
|
+
console.log('Run `slope help` for the bounded human surface, or `slope help <command>` for detailed usage.\n');
|
|
59
100
|
}
|
|
60
101
|
function printCommandDetail(meta) {
|
|
61
102
|
const displayName = meta.cmd === 'index-cmd' ? 'index' : meta.cmd;
|
|
62
|
-
console.log(`\nslope ${displayName}
|
|
103
|
+
console.log(`\nslope ${displayName} - ${meta.desc}\n`);
|
|
63
104
|
console.log(` Category: ${meta.category}\n`);
|
|
105
|
+
console.log(` Audience: ${AUDIENCE_LABELS[meta.audience]}\n`);
|
|
64
106
|
if (meta.subcommands && meta.subcommands.length > 0) {
|
|
65
107
|
console.log(' Subcommands:\n');
|
|
66
108
|
for (const sub of meta.subcommands) {
|
|
@@ -82,6 +124,12 @@ function printCommandDetail(meta) {
|
|
|
82
124
|
console.log('');
|
|
83
125
|
}
|
|
84
126
|
}
|
|
127
|
+
function printCommandRow(cmd, indent, includeAudience = false) {
|
|
128
|
+
const name = cmd.cmd === 'index-cmd' ? 'index' : cmd.cmd;
|
|
129
|
+
const prefix = ' '.repeat(indent);
|
|
130
|
+
const audience = includeAudience ? ` [${AUDIENCE_LABELS[cmd.audience]}]` : '';
|
|
131
|
+
console.log(`${prefix}${name.padEnd(14)} ${cmd.desc}${audience}`);
|
|
132
|
+
}
|
|
85
133
|
function suggestClosest(input) {
|
|
86
134
|
const names = CLI_COMMAND_REGISTRY
|
|
87
135
|
.filter(c => !CLI_INTERNAL_MODULES.includes(c.cmd))
|
|
@@ -92,7 +140,7 @@ function suggestClosest(input) {
|
|
|
92
140
|
if (matches.length > 0) {
|
|
93
141
|
console.error(`Did you mean: ${matches.join(', ')}?`);
|
|
94
142
|
}
|
|
95
|
-
console.error(`\nRun \`slope help\`
|
|
143
|
+
console.error(`\nRun \`slope help\` for the human surface or \`slope help --all\` for all commands.`);
|
|
96
144
|
process.exit(1);
|
|
97
145
|
}
|
|
98
146
|
//# sourceMappingURL=help.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/cli/commands/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG5E;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAc;IAC9C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/cli/commands/help.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { RoadmapTicket } from '../../core/index.js';
|
|
2
|
+
interface NowSnapshot {
|
|
3
|
+
sprint: number;
|
|
4
|
+
sprintLabel: string;
|
|
5
|
+
source: string;
|
|
6
|
+
roadmap?: {
|
|
7
|
+
name: string;
|
|
8
|
+
theme?: string;
|
|
9
|
+
phase?: string;
|
|
10
|
+
phaseProgress?: string;
|
|
11
|
+
status: string;
|
|
12
|
+
};
|
|
13
|
+
sprintState?: {
|
|
14
|
+
phase: string;
|
|
15
|
+
pendingGates: string[];
|
|
16
|
+
};
|
|
17
|
+
claims: {
|
|
18
|
+
total: number;
|
|
19
|
+
ticketClaims: number;
|
|
20
|
+
};
|
|
21
|
+
nextAction: string;
|
|
22
|
+
nextTicket?: RoadmapTicket;
|
|
23
|
+
}
|
|
24
|
+
declare function buildNowSnapshot(cwd: string, flags: Record<string, string>): Promise<NowSnapshot>;
|
|
25
|
+
export declare function nowCommand(args: string[]): Promise<void>;
|
|
26
|
+
export declare const testInternals: {
|
|
27
|
+
buildNowSnapshot: typeof buildNowSnapshot;
|
|
28
|
+
};
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=now.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"now.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/now.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoC,aAAa,EAAe,MAAM,qBAAqB,CAAC;AAMxG,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,WAAW,CAAC,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,EAAE,CAAC;KACxB,CAAC;IACF,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,aAAa,CAAC;CAC5B;AAwDD,iBAAe,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAkDhG;AAgCD,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAa9D;AAED,eAAO,MAAM,aAAa;;CAEzB,CAAC"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { formatSprintLabel, formatSprintNumber, isRoadmapSprintPending, loadScorecards, parseSprintNumber } from '../../core/index.js';
|
|
2
|
+
import { loadConfig } from '../config.js';
|
|
3
|
+
import { inferSprintContext, loadRoadmapForInference } from '../sprint-inference.js';
|
|
4
|
+
import { loadSprintState, pendingGates } from '../sprint-state.js';
|
|
5
|
+
import { resolveStore } from '../store.js';
|
|
6
|
+
function parseArgs(args) {
|
|
7
|
+
const result = {};
|
|
8
|
+
for (const arg of args) {
|
|
9
|
+
const match = arg.match(/^--(\w[\w-]*)(?:=(.+))?$/);
|
|
10
|
+
if (match)
|
|
11
|
+
result[match[1]] = match[2] ?? 'true';
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
function sprintStatus(sprint, completed, currentSprint) {
|
|
16
|
+
if (!sprint)
|
|
17
|
+
return 'not in roadmap';
|
|
18
|
+
const explicit = sprint.status;
|
|
19
|
+
if (explicit === 'superseded')
|
|
20
|
+
return 'superseded';
|
|
21
|
+
if (explicit === 'complete' || completed.has(sprint.id))
|
|
22
|
+
return 'complete';
|
|
23
|
+
if (sprint.id === currentSprint)
|
|
24
|
+
return 'active';
|
|
25
|
+
if (isRoadmapSprintPending(sprint))
|
|
26
|
+
return 'pending';
|
|
27
|
+
return explicit ?? 'unknown';
|
|
28
|
+
}
|
|
29
|
+
function isTerminal(sprint, completed) {
|
|
30
|
+
const explicit = sprint.status;
|
|
31
|
+
return explicit === 'complete' || explicit === 'superseded' || completed.has(sprint.id);
|
|
32
|
+
}
|
|
33
|
+
function formatPhaseProgress(roadmap, sprint, completed) {
|
|
34
|
+
const phase = roadmap.phases.find(p => p.sprints.includes(sprint));
|
|
35
|
+
if (!phase)
|
|
36
|
+
return undefined;
|
|
37
|
+
const phaseSprints = roadmap.sprints.filter(s => phase.sprints.includes(s.id));
|
|
38
|
+
const completedCount = phaseSprints.filter(s => isTerminal(s, completed)).length;
|
|
39
|
+
return {
|
|
40
|
+
name: phase.name,
|
|
41
|
+
progress: `${completedCount}/${phaseSprints.length}`,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function findNextTicket(sprint, claims) {
|
|
45
|
+
if (!sprint)
|
|
46
|
+
return undefined;
|
|
47
|
+
const claimedTargets = new Set(claims.map(c => c.target));
|
|
48
|
+
return sprint.tickets.find(ticket => !claimedTargets.has(ticket.key)) ?? sprint.tickets[0];
|
|
49
|
+
}
|
|
50
|
+
function buildNextAction(snapshot) {
|
|
51
|
+
if (!snapshot.roadmap) {
|
|
52
|
+
return 'Run slope init or slope roadmap status to establish project direction.';
|
|
53
|
+
}
|
|
54
|
+
if (snapshot.nextTicket) {
|
|
55
|
+
return `Start ${snapshot.nextTicket.key}: ${snapshot.nextTicket.title}`;
|
|
56
|
+
}
|
|
57
|
+
if (snapshot.sprintState && snapshot.sprintState.pendingGates.length > 0) {
|
|
58
|
+
return `Clear pending gates: ${snapshot.sprintState.pendingGates.join(', ')}`;
|
|
59
|
+
}
|
|
60
|
+
return `Review ${snapshot.sprintLabel} and prepare closeout.`;
|
|
61
|
+
}
|
|
62
|
+
async function buildNowSnapshot(cwd, flags) {
|
|
63
|
+
const config = loadConfig(cwd);
|
|
64
|
+
const inferred = inferSprintContext(cwd, config);
|
|
65
|
+
const parsedSprint = flags.sprint ? parseSprintNumber(flags.sprint) : inferred.sprint;
|
|
66
|
+
if (parsedSprint == null) {
|
|
67
|
+
throw new Error(`Invalid sprint number: ${flags.sprint}`);
|
|
68
|
+
}
|
|
69
|
+
const sprint = parsedSprint;
|
|
70
|
+
const sprintLabel = formatSprintLabel(sprint);
|
|
71
|
+
const roadmap = loadRoadmapForInference(cwd, config) ?? undefined;
|
|
72
|
+
const scorecards = loadScorecards(config, cwd);
|
|
73
|
+
const completed = new Set(scorecards.map(card => card.sprint_number));
|
|
74
|
+
const current = roadmap?.sprints.find(s => s.id === sprint);
|
|
75
|
+
const phase = roadmap ? formatPhaseProgress(roadmap, sprint, completed) : undefined;
|
|
76
|
+
const state = loadSprintState(cwd);
|
|
77
|
+
const store = await resolveStore(cwd);
|
|
78
|
+
let claims;
|
|
79
|
+
try {
|
|
80
|
+
claims = await store.list(sprint);
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
store.close();
|
|
84
|
+
}
|
|
85
|
+
const partial = {
|
|
86
|
+
sprint,
|
|
87
|
+
sprintLabel,
|
|
88
|
+
source: flags.sprint ? 'flag' : inferred.source,
|
|
89
|
+
roadmap: roadmap ? {
|
|
90
|
+
name: roadmap.name,
|
|
91
|
+
theme: current?.theme,
|
|
92
|
+
phase: phase?.name,
|
|
93
|
+
phaseProgress: phase?.progress,
|
|
94
|
+
status: sprintStatus(current, completed, sprint),
|
|
95
|
+
} : undefined,
|
|
96
|
+
sprintState: state?.sprint === sprint ? {
|
|
97
|
+
phase: state.phase,
|
|
98
|
+
pendingGates: pendingGates(state),
|
|
99
|
+
} : undefined,
|
|
100
|
+
claims: {
|
|
101
|
+
total: claims.length,
|
|
102
|
+
ticketClaims: claims.filter(c => c.scope === 'ticket').length,
|
|
103
|
+
},
|
|
104
|
+
nextTicket: findNextTicket(current, claims),
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
...partial,
|
|
108
|
+
nextAction: buildNextAction(partial),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function printNowSnapshot(snapshot) {
|
|
112
|
+
console.log('\nSLOPE Now');
|
|
113
|
+
console.log('='.repeat(32));
|
|
114
|
+
const theme = snapshot.roadmap?.theme ? ` - ${snapshot.roadmap.theme}` : '';
|
|
115
|
+
console.log(`Current: ${snapshot.sprintLabel}${theme}`);
|
|
116
|
+
if (snapshot.roadmap?.phase) {
|
|
117
|
+
const progress = snapshot.roadmap.phaseProgress ? ` (${snapshot.roadmap.phaseProgress})` : '';
|
|
118
|
+
console.log(`Phase: ${snapshot.roadmap.phase}${progress}`);
|
|
119
|
+
}
|
|
120
|
+
console.log(`Roadmap: ${snapshot.roadmap?.status ?? 'not found'} (${snapshot.source})`);
|
|
121
|
+
console.log(`Sprint state: ${snapshot.sprintState?.phase ?? 'not started'}`);
|
|
122
|
+
console.log(`Claims: ${snapshot.claims.total} active, ${snapshot.claims.ticketClaims} ticket`);
|
|
123
|
+
console.log(`Next: ${snapshot.nextAction}`);
|
|
124
|
+
if (snapshot.nextTicket) {
|
|
125
|
+
console.log(`Start: slope start --ticket=${snapshot.nextTicket.key}`);
|
|
126
|
+
}
|
|
127
|
+
console.log(`More: slope roadmap status --sprint=${formatSprintNumber(snapshot.sprint)}\n`);
|
|
128
|
+
}
|
|
129
|
+
function printUsage() {
|
|
130
|
+
console.log(`
|
|
131
|
+
slope now - Compact current-state cockpit
|
|
132
|
+
|
|
133
|
+
Usage:
|
|
134
|
+
slope now [--sprint=N] [--json]
|
|
135
|
+
|
|
136
|
+
Shows the current sprint, phase, sprint state, claim count, and next human action.
|
|
137
|
+
`);
|
|
138
|
+
}
|
|
139
|
+
export async function nowCommand(args) {
|
|
140
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
141
|
+
printUsage();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const flags = parseArgs(args);
|
|
145
|
+
const snapshot = await buildNowSnapshot(process.cwd(), flags);
|
|
146
|
+
if (flags.json === 'true') {
|
|
147
|
+
console.log(JSON.stringify(snapshot, null, 2));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
printNowSnapshot(snapshot);
|
|
151
|
+
}
|
|
152
|
+
export const testInternals = {
|
|
153
|
+
buildNowSnapshot,
|
|
154
|
+
};
|
|
155
|
+
//# sourceMappingURL=now.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"now.js","sourceRoot":"","sources":["../../../src/cli/commands/now.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roadmap.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/roadmap.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"roadmap.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/roadmap.ts"],"names":[],"mappings":"AAosBA,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwDlE"}
|
|
@@ -3,6 +3,7 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { parseRoadmap, validateRoadmap, castRoadmapStructure, findShippedSprintsOnMain, compareSprintIds, computeCriticalPath, findParallelOpportunities, formatSprintLabel, formatRoadmapSummary, formatStrategicContext, isRoadmapSprintPending, loadScorecards, loadVision, parseSprintNumber, analyzeBacklog, mergeBacklogs, runAnalyzers, estimateComplexity, generateRoadmapFromVision, RoadmapGenerationError, } from '../../core/index.js';
|
|
4
4
|
import { loadConfig } from '../config.js';
|
|
5
5
|
import { buildRoadmapReality, formatRoadmapRealitySection } from '../pre-sprint-reality.js';
|
|
6
|
+
import { interviewCommand } from './interview.js';
|
|
6
7
|
// --- Helpers ---
|
|
7
8
|
function parseArgs(args) {
|
|
8
9
|
const result = {};
|
|
@@ -15,12 +16,46 @@ function parseArgs(args) {
|
|
|
15
16
|
}
|
|
16
17
|
const DEFAULT_ROADMAP_PATH = 'docs/backlog/roadmap.json';
|
|
17
18
|
const TERMINAL_ROADMAP_STATUSES = new Set(['complete', 'superseded']);
|
|
19
|
+
const DEFAULT_UPCOMING_LIMIT = 3;
|
|
18
20
|
function getRoadmapStatus(sprint) {
|
|
19
21
|
return sprint.status;
|
|
20
22
|
}
|
|
21
23
|
function isTerminalRoadmapSprint(sprint, completedSprints) {
|
|
22
24
|
return completedSprints.has(sprint.id) || TERMINAL_ROADMAP_STATUSES.has(getRoadmapStatus(sprint) ?? '');
|
|
23
25
|
}
|
|
26
|
+
function blockedByForSprint(roadmap, sprint, completedSprints) {
|
|
27
|
+
return (sprint.depends_on ?? []).filter(dep => {
|
|
28
|
+
const dependency = roadmap.sprints.find(s => s.id === dep);
|
|
29
|
+
return dependency ? !isTerminalRoadmapSprint(dependency, completedSprints) : !completedSprints.has(dep);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function statusLabelForSprint(roadmap, sprint, currentSprint, completedSprints) {
|
|
33
|
+
const explicitStatus = getRoadmapStatus(sprint);
|
|
34
|
+
const isCompleted = completedSprints.has(sprint.id) || explicitStatus === 'complete';
|
|
35
|
+
const isSuperseded = explicitStatus === 'superseded';
|
|
36
|
+
const isCurrent = sprint.id === currentSprint;
|
|
37
|
+
const blockedBy = blockedByForSprint(roadmap, sprint, completedSprints);
|
|
38
|
+
if (isSuperseded)
|
|
39
|
+
return '\u21B7 superseded';
|
|
40
|
+
if (isCompleted)
|
|
41
|
+
return '\u2713 completed';
|
|
42
|
+
if (isCurrent)
|
|
43
|
+
return '\u25B6 active';
|
|
44
|
+
if (blockedBy.length > 0)
|
|
45
|
+
return `\u2718 blocked by ${blockedBy.map(formatSprintLabel).join(', ')}`;
|
|
46
|
+
return '\u25CB pending';
|
|
47
|
+
}
|
|
48
|
+
function phaseForSprint(roadmap, sprintId) {
|
|
49
|
+
return roadmap.phases.find(phase => phase.sprints?.includes(sprintId));
|
|
50
|
+
}
|
|
51
|
+
function formatPhaseProgress(roadmap, phase, completedSprints) {
|
|
52
|
+
const phaseSprints = roadmap.sprints.filter(s => phase.sprints.includes(s.id));
|
|
53
|
+
const completed = phaseSprints.filter(s => isTerminalRoadmapSprint(s, completedSprints)).length;
|
|
54
|
+
return `${phase.name || 'Unnamed Phase'} (${completed}/${phaseSprints.length})`;
|
|
55
|
+
}
|
|
56
|
+
function sortedRoadmapSprints(roadmap) {
|
|
57
|
+
return [...roadmap.sprints].sort((a, b) => compareSprintIds(a.id, b.id));
|
|
58
|
+
}
|
|
24
59
|
function resolveRoadmapPath(flags, cwd) {
|
|
25
60
|
if (flags.path)
|
|
26
61
|
return flags.path;
|
|
@@ -259,6 +294,14 @@ function statusSubcommand(flags, cwd) {
|
|
|
259
294
|
const scorecards = loadScorecards(config, cwd);
|
|
260
295
|
const currentSprint = resolveSprint(flags, cwd, roadmap, scorecards);
|
|
261
296
|
const completedSprints = new Set(scorecards.map(s => s.sprint_number));
|
|
297
|
+
if (flags.full === 'true' || flags.history === 'true') {
|
|
298
|
+
printFullRoadmapStatus(roadmap, currentSprint, completedSprints);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
printCompactRoadmapStatus(roadmap, currentSprint, completedSprints, cwd);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function printFullRoadmapStatus(roadmap, currentSprint, completedSprints) {
|
|
262
305
|
console.log(`\n# Roadmap Status — ${roadmap.name}`);
|
|
263
306
|
console.log('\u2550'.repeat(40));
|
|
264
307
|
console.log(`\nCurrent sprint: ${formatSprintLabel(currentSprint)}`);
|
|
@@ -313,6 +356,82 @@ function statusSubcommand(flags, cwd) {
|
|
|
313
356
|
console.log('');
|
|
314
357
|
}
|
|
315
358
|
}
|
|
359
|
+
function printCompactRoadmapStatus(roadmap, currentSprint, completedSprints, cwd) {
|
|
360
|
+
const current = roadmap.sprints.find(s => s.id === currentSprint);
|
|
361
|
+
const currentLabel = current
|
|
362
|
+
? `${formatSprintLabel(current.id)} ${current.theme || 'Untitled Sprint'}`
|
|
363
|
+
: `${formatSprintLabel(currentSprint)} (not found in roadmap)`;
|
|
364
|
+
const currentIsPending = current ? isRoadmapSprintPending(current) : false;
|
|
365
|
+
const currentPhase = phaseForSprint(roadmap, currentSprint);
|
|
366
|
+
const pendingAfterCurrent = sortedRoadmapSprints(roadmap)
|
|
367
|
+
.filter(s => isRoadmapSprintPending(s) && s.id !== currentSprint && compareSprintIds(s.id, currentSprint) > 0);
|
|
368
|
+
const nextReady = pendingAfterCurrent.find(s => blockedByForSprint(roadmap, s, completedSprints).length === 0);
|
|
369
|
+
const upcoming = pendingAfterCurrent.slice(0, DEFAULT_UPCOMING_LIMIT);
|
|
370
|
+
const realityLines = formatRoadmapRealitySection(buildRoadmapReality(cwd, roadmap), undefined, 5).slice(1);
|
|
371
|
+
console.log(`\n# Roadmap Status - ${roadmap.name}`);
|
|
372
|
+
console.log('\u2550'.repeat(40));
|
|
373
|
+
console.log(`\nCurrent: ${currentLabel}`);
|
|
374
|
+
if (currentPhase)
|
|
375
|
+
console.log(`Phase: ${formatPhaseProgress(roadmap, currentPhase, completedSprints)}`);
|
|
376
|
+
console.log('\nReality checks:');
|
|
377
|
+
if (realityLines.length === 0) {
|
|
378
|
+
console.log(' None');
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
for (const line of realityLines)
|
|
382
|
+
console.log(` ${line.trim()}`);
|
|
383
|
+
}
|
|
384
|
+
console.log('\nActive sprint:');
|
|
385
|
+
if (!current) {
|
|
386
|
+
console.log(` ${formatSprintLabel(currentSprint)} is not defined in the roadmap.`);
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
console.log(` ${formatSprintLabel(current.id)} ${current.theme || 'Untitled Sprint'} - ${statusLabelForSprint(roadmap, current, currentSprint, completedSprints)}`);
|
|
390
|
+
if ((current.depends_on ?? []).length > 0) {
|
|
391
|
+
const deps = current.depends_on.map(dep => {
|
|
392
|
+
const sprint = roadmap.sprints.find(s => s.id === dep);
|
|
393
|
+
if (!sprint)
|
|
394
|
+
return `${formatSprintLabel(dep)} missing`;
|
|
395
|
+
return `${formatSprintLabel(dep)} ${statusLabelForSprint(roadmap, sprint, currentSprint, completedSprints).replace(/^[^\w]+ /, '')}`;
|
|
396
|
+
});
|
|
397
|
+
console.log(` Dependencies: ${deps.join(', ')}`);
|
|
398
|
+
}
|
|
399
|
+
for (const ticket of current.tickets ?? []) {
|
|
400
|
+
console.log(` - ${ticket.key}: ${ticket.title}`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
console.log('\nNext ready:');
|
|
404
|
+
if (nextReady) {
|
|
405
|
+
console.log(` ${formatSprintLabel(nextReady.id)} ${nextReady.theme || 'Untitled Sprint'} - ${statusLabelForSprint(roadmap, nextReady, currentSprint, completedSprints)}`);
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
console.log(' None yet');
|
|
409
|
+
}
|
|
410
|
+
console.log(`\nUpcoming (${upcoming.length}/${Math.min(DEFAULT_UPCOMING_LIMIT, pendingAfterCurrent.length)}):`);
|
|
411
|
+
if (upcoming.length === 0) {
|
|
412
|
+
console.log(' None');
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
for (const sprint of upcoming) {
|
|
416
|
+
console.log(` ${formatSprintLabel(sprint.id)} ${sprint.theme || 'Untitled Sprint'} - ${statusLabelForSprint(roadmap, sprint, currentSprint, completedSprints)}`);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
console.log('\nRecommended next action:');
|
|
420
|
+
if (realityLines.some(line => line.includes('[error]'))) {
|
|
421
|
+
console.log(' Resolve the first roadmap reality error before advancing the lane.');
|
|
422
|
+
}
|
|
423
|
+
else if (currentIsPending && current?.tickets?.length) {
|
|
424
|
+
const first = current.tickets[0];
|
|
425
|
+
console.log(` Work ${first.key}: ${first.title}`);
|
|
426
|
+
}
|
|
427
|
+
else if (nextReady) {
|
|
428
|
+
console.log(` Start ${formatSprintLabel(nextReady.id)}: ${nextReady.theme || 'Untitled Sprint'}`);
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
console.log(' No roadmap action is currently ready.');
|
|
432
|
+
}
|
|
433
|
+
console.log('\nFor the full roadmap history, run: slope roadmap status --full\n');
|
|
434
|
+
}
|
|
316
435
|
function showSubcommand(flags, cwd) {
|
|
317
436
|
const roadmap = loadRoadmapFile(flags, cwd);
|
|
318
437
|
if (!roadmap) {
|
|
@@ -514,14 +633,18 @@ export async function roadmapCommand(args) {
|
|
|
514
633
|
case 'generate':
|
|
515
634
|
await generateSubcommand(flags, cwd);
|
|
516
635
|
break;
|
|
636
|
+
case 'interview':
|
|
637
|
+
await interviewCommand(args.slice(1));
|
|
638
|
+
break;
|
|
517
639
|
default:
|
|
518
640
|
console.log(`
|
|
519
641
|
slope roadmap — Strategic planning tools
|
|
520
642
|
|
|
521
643
|
Usage:
|
|
644
|
+
slope roadmap interview [--agent] [--force] Run project interview for planning input
|
|
522
645
|
slope roadmap validate [--path=<file>] Schema + dependency graph checks
|
|
523
646
|
slope roadmap review [--path=<file>] Automated architect review
|
|
524
|
-
slope roadmap status [--path=<file>] [--sprint=N]
|
|
647
|
+
slope roadmap status [--path=<file>] [--sprint=N] [--full] Compact current progress
|
|
525
648
|
slope roadmap show [--path=<file>] Render summary (critical path, parallel tracks)
|
|
526
649
|
slope roadmap sync [--path=<file>] [--dry-run] Sync scorecards into roadmap
|
|
527
650
|
slope roadmap generate [--path=<file>] [--dry-run] Generate from vision + concrete backlog signals
|
|
@@ -529,8 +652,13 @@ Usage:
|
|
|
529
652
|
Options:
|
|
530
653
|
--path=<file> Path to roadmap JSON (default: docs/backlog/roadmap.json)
|
|
531
654
|
--sprint=N Override current sprint number (for status)
|
|
655
|
+
--full Show full roadmap history for status
|
|
532
656
|
--dry-run Show what would change without writing (for sync and generate)
|
|
533
657
|
|
|
658
|
+
Interview delegates to \`slope interview\`. Use \`--agent\` for JSON I/O, or
|
|
659
|
+
\`slope vision create/update\` plus \`slope roadmap generate\` when you already
|
|
660
|
+
have planning answers.
|
|
661
|
+
|
|
534
662
|
Generate requires concrete backlog signals from source TODO/FIXME/HACK comments
|
|
535
663
|
or synced issue data. It fails instead of creating placeholder planning tickets
|
|
536
664
|
when there is nothing concrete to mine.
|