@specforge/mcp 3.0.6 → 3.1.0
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/cli/commands/index.d.ts +2 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +2 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +268 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/init.types.d.ts +39 -0
- package/dist/cli/commands/init.types.d.ts.map +1 -1
- package/dist/cli/commands/init.types.js +18 -0
- package/dist/cli/commands/init.types.js.map +1 -1
- package/dist/cli/commands/plan.d.ts +18 -0
- package/dist/cli/commands/plan.d.ts.map +1 -0
- package/dist/cli/commands/plan.js +154 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/plan.types.d.ts +60 -0
- package/dist/cli/commands/plan.types.d.ts.map +1 -0
- package/dist/cli/commands/plan.types.js +8 -0
- package/dist/cli/commands/plan.types.js.map +1 -0
- package/dist/cli/commands/spec-activate.d.ts +29 -0
- package/dist/cli/commands/spec-activate.d.ts.map +1 -0
- package/dist/cli/commands/spec-activate.js +155 -0
- package/dist/cli/commands/spec-activate.js.map +1 -0
- package/dist/cli/commands/spec-activate.types.d.ts +24 -0
- package/dist/cli/commands/spec-activate.types.d.ts.map +1 -0
- package/dist/cli/commands/spec-activate.types.js +8 -0
- package/dist/cli/commands/spec-activate.types.js.map +1 -0
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +89 -1
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/status.types.d.ts +2 -0
- package/dist/cli/commands/status.types.d.ts.map +1 -1
- package/dist/cli/commands/status.types.js.map +1 -1
- package/dist/cli/config/agent-teams.types.d.ts +194 -0
- package/dist/cli/config/agent-teams.types.d.ts.map +1 -0
- package/dist/cli/config/agent-teams.types.js +36 -0
- package/dist/cli/config/agent-teams.types.js.map +1 -0
- package/dist/cli/config/index.d.ts +2 -0
- package/dist/cli/config/index.d.ts.map +1 -1
- package/dist/cli/config/index.js +2 -0
- package/dist/cli/config/index.js.map +1 -1
- package/dist/cli/config/loader.d.ts +36 -2
- package/dist/cli/config/loader.d.ts.map +1 -1
- package/dist/cli/config/loader.js +65 -0
- package/dist/cli/config/loader.js.map +1 -1
- package/dist/cli/config/validation.d.ts +69 -0
- package/dist/cli/config/validation.d.ts.map +1 -0
- package/dist/cli/config/validation.js +295 -0
- package/dist/cli/config/validation.js.map +1 -0
- package/dist/cli/config/writer.d.ts +39 -0
- package/dist/cli/config/writer.d.ts.map +1 -1
- package/dist/cli/config/writer.js +58 -0
- package/dist/cli/config/writer.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +5 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/lib/index.d.ts +3 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +3 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/monorepo-detector.d.ts +31 -0
- package/dist/lib/monorepo-detector.d.ts.map +1 -0
- package/dist/lib/monorepo-detector.js +271 -0
- package/dist/lib/monorepo-detector.js.map +1 -0
- package/dist/lib/prompt-generator.d.ts +65 -0
- package/dist/lib/prompt-generator.d.ts.map +1 -0
- package/dist/lib/prompt-generator.js +172 -0
- package/dist/lib/prompt-generator.js.map +1 -0
- package/dist/lib/strategy-analyzer.d.ts +59 -0
- package/dist/lib/strategy-analyzer.d.ts.map +1 -0
- package/dist/lib/strategy-analyzer.js +137 -0
- package/dist/lib/strategy-analyzer.js.map +1 -0
- package/dist/tools/core/blueprint.d.ts.map +1 -1
- package/dist/tools/core/blueprint.js +6 -0
- package/dist/tools/core/blueprint.js.map +1 -1
- package/dist/tools/core/context-helper.d.ts +22 -0
- package/dist/tools/core/context-helper.d.ts.map +1 -1
- package/dist/tools/core/context-helper.js +37 -1
- package/dist/tools/core/context-helper.js.map +1 -1
- package/dist/tools/core/workspace-files.d.ts +49 -0
- package/dist/tools/core/workspace-files.d.ts.map +1 -0
- package/dist/tools/core/workspace-files.js +259 -0
- package/dist/tools/core/workspace-files.js.map +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +147 -0
- package/dist/tools/index.js.map +1 -1
- package/package.json +3 -2
- package/src/cli/templates/agents/content/core/sfag-implementer.ts +113 -0
- package/src/cli/templates/agents/content/core/sfag-orchestrator.ts +107 -0
- package/src/cli/templates/agents/content/core/sfag-spec-creator.ts +126 -0
- package/src/cli/templates/agents/content/core/sfag-ticket-implementer.ts +132 -0
- package/src/cli/templates/agents/content/research/sfag-package-researcher.ts +153 -0
- package/src/cli/templates/agents/content/task-type/sfag-api-implementer.ts +132 -0
- package/src/cli/templates/agents/content/task-type/sfag-docs-writer.ts +183 -0
- package/src/cli/templates/agents/content/task-type/sfag-frontend-builder.ts +141 -0
- package/src/cli/templates/agents/content/task-type/sfag-infra-architect.ts +149 -0
- package/src/cli/templates/agents/content/task-type/sfag-schema-designer.ts +132 -0
- package/src/cli/templates/agents/content/task-type/sfag-test-writer.ts +171 -0
- package/src/cli/templates/agents/index.ts +74 -0
- package/src/cli/templates/commands.ts +179 -0
- package/src/cli/templates/content/sf-autonomous.ts +78 -0
- package/src/cli/templates/content/sf-blockers.ts +68 -0
- package/src/cli/templates/content/sf-commit.ts +78 -0
- package/src/cli/templates/content/sf-context.ts +64 -0
- package/src/cli/templates/content/sf-create-epics.ts +129 -0
- package/src/cli/templates/content/sf-create-spec.ts +136 -0
- package/src/cli/templates/content/sf-create-tickets.ts +148 -0
- package/src/cli/templates/content/sf-epic.ts +69 -0
- package/src/cli/templates/content/sf-help.ts +61 -0
- package/src/cli/templates/content/sf-import.ts +88 -0
- package/src/cli/templates/content/sf-init.ts +61 -0
- package/src/cli/templates/content/sf-next.ts +67 -0
- package/src/cli/templates/content/sf-reset.ts +78 -0
- package/src/cli/templates/content/sf-review.ts +67 -0
- package/src/cli/templates/content/sf-search.ts +64 -0
- package/src/cli/templates/content/sf-status.ts +67 -0
- package/src/cli/templates/content/sf-ticket.ts +76 -0
- package/src/cli/templates/content/sf-validate.ts +78 -0
- package/src/cli/templates/index.ts +16 -0
- package/src/cli/templates/skills/specforge-conventions.md +109 -0
- package/src/cli/templates/skills/specforge-orchestrator.md +401 -0
- package/src/cli/templates/skills/specforge-validator.md +122 -0
- package/src/cli/templates/skills/specforge-worker.md +378 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Command
|
|
3
|
+
*
|
|
4
|
+
* Dry-run visualization of the Agent Teams implementation plan.
|
|
5
|
+
* Calls get_implementation_plan via MCP and displays an ASCII tree
|
|
6
|
+
* showing team-worker mapping, execution phases, and dependency status.
|
|
7
|
+
*/
|
|
8
|
+
import ora from 'ora';
|
|
9
|
+
import { resolveConfig } from '../config/index.js';
|
|
10
|
+
import { loadProjectConfig, getActiveSpecification } from '../config/loader.js';
|
|
11
|
+
import { withErrorHandler, CliError, NetworkError } from '../middleware/error-handler.js';
|
|
12
|
+
import { printBlank, printJson } from '../ui/output.js';
|
|
13
|
+
import { colors } from '../ui/colors.js';
|
|
14
|
+
import { ApiClient } from '../../client/api-client.js';
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the specification ID from options or active spec config
|
|
17
|
+
*/
|
|
18
|
+
function resolveSpecificationId(options, configSpecId) {
|
|
19
|
+
if (options.spec) {
|
|
20
|
+
return options.spec;
|
|
21
|
+
}
|
|
22
|
+
// Try active specification from .specforge.json
|
|
23
|
+
const projectConfig = loadProjectConfig();
|
|
24
|
+
const activeSpec = getActiveSpecification(projectConfig);
|
|
25
|
+
if (activeSpec?.id) {
|
|
26
|
+
return activeSpec.id;
|
|
27
|
+
}
|
|
28
|
+
// Fall back to specificationId from resolved config
|
|
29
|
+
if (configSpecId) {
|
|
30
|
+
return configSpecId;
|
|
31
|
+
}
|
|
32
|
+
throw new CliError('No active specification', 1, "Run 'specforge spec activate <id>' to set an active specification, or use --spec <id>");
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Render the ASCII tree visualization of the implementation plan
|
|
36
|
+
*/
|
|
37
|
+
function renderPlanTree(plan) {
|
|
38
|
+
printBlank();
|
|
39
|
+
// Strategy header
|
|
40
|
+
console.log(`${colors.bold('Strategy:')} ${colors.primary(plan.strategy)} ${colors.muted(`(${plan.reasoning})`)}`);
|
|
41
|
+
printBlank();
|
|
42
|
+
if (plan.teams.length === 0) {
|
|
43
|
+
console.log(colors.muted('No teams to display. The specification may have no remaining work.'));
|
|
44
|
+
printBlank();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Build a lookup: team name -> phase number
|
|
48
|
+
const teamPhaseMap = new Map();
|
|
49
|
+
for (const phase of plan.executionOrder) {
|
|
50
|
+
for (const teamName of phase.teams) {
|
|
51
|
+
teamPhaseMap.set(teamName, phase.phase);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Render by execution phase
|
|
55
|
+
for (const phase of plan.executionOrder) {
|
|
56
|
+
const phaseLabel = phase.phase === 1
|
|
57
|
+
? 'parallel'
|
|
58
|
+
: `after phase ${phase.phase - 1}`;
|
|
59
|
+
console.log(colors.bold(`Phase ${phase.phase}`) + colors.muted(` (${phaseLabel}):`));
|
|
60
|
+
// Find teams in this phase
|
|
61
|
+
const phaseTeams = plan.teams.filter(t => phase.teams.includes(t.name));
|
|
62
|
+
for (const team of phaseTeams) {
|
|
63
|
+
console.log(` ${colors.bold('Team:')} ${colors.primary(team.name)} ${colors.muted(`(${team.suggestedWorkers} worker${team.suggestedWorkers === 1 ? '' : 's'})`)}`);
|
|
64
|
+
for (const task of team.tasks) {
|
|
65
|
+
const isBlocked = task.blockedBy.length > 0;
|
|
66
|
+
if (isBlocked) {
|
|
67
|
+
const deps = task.blockedBy.join(', ');
|
|
68
|
+
console.log(` ${colors.warning('[BLOCKED]')} ${task.slug}: ${task.title} ${colors.muted(`(by ${deps})`)}`);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
console.log(` ${colors.success('[READY]')} ${task.slug}: ${task.title}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
printBlank();
|
|
76
|
+
}
|
|
77
|
+
// Summary line
|
|
78
|
+
console.log(`${colors.bold('Total:')} ${plan.estimatedTotalTickets} tickets, ` +
|
|
79
|
+
`${plan.estimatedParallelizableTickets} parallelizable`);
|
|
80
|
+
printBlank();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Plan command action handler
|
|
84
|
+
*/
|
|
85
|
+
export async function planAction(options) {
|
|
86
|
+
const config = resolveConfig();
|
|
87
|
+
if (!config.apiKey) {
|
|
88
|
+
throw new CliError('Not authenticated', 1, 'Run `specforge login` to authenticate first');
|
|
89
|
+
}
|
|
90
|
+
const specificationId = resolveSpecificationId(options, config.specificationId);
|
|
91
|
+
const spinner = ora({
|
|
92
|
+
text: 'Generating implementation plan...',
|
|
93
|
+
color: 'cyan',
|
|
94
|
+
}).start();
|
|
95
|
+
try {
|
|
96
|
+
const client = new ApiClient({
|
|
97
|
+
apiKey: config.apiKey,
|
|
98
|
+
apiUrl: config.apiUrl,
|
|
99
|
+
debug: config.debug,
|
|
100
|
+
});
|
|
101
|
+
const plan = await client.call('get_implementation_plan', {
|
|
102
|
+
specificationId,
|
|
103
|
+
...(options.strategy && options.strategy !== 'auto' ? { strategy: options.strategy } : {}),
|
|
104
|
+
});
|
|
105
|
+
spinner.stop();
|
|
106
|
+
if (options.json) {
|
|
107
|
+
printJson(plan);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
renderPlanTree(plan);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
spinner.fail('Failed to generate implementation plan');
|
|
115
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
116
|
+
if (message.includes('401') || message.includes('Unauthorized')) {
|
|
117
|
+
throw new CliError('Authentication failed', 1, 'Your API key may be invalid. Run `specforge login` to re-authenticate');
|
|
118
|
+
}
|
|
119
|
+
if (message.includes('404') || message.includes('Not Found') || message.includes('not found')) {
|
|
120
|
+
throw new CliError(`Specification not found: ${specificationId}`, 1, "Run 'specforge specs' to list available specifications.");
|
|
121
|
+
}
|
|
122
|
+
throw new NetworkError(`Failed to generate plan: ${message}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Register plan command with Commander
|
|
127
|
+
*/
|
|
128
|
+
export function registerPlanCommand(program) {
|
|
129
|
+
program
|
|
130
|
+
.command('plan')
|
|
131
|
+
.description('Preview Agent Teams implementation plan (dry-run)')
|
|
132
|
+
.option('--strategy <type>', 'Override strategy: epic-as-team | spec-as-team | single-session | auto')
|
|
133
|
+
.option('--spec <id>', 'Specification ID (overrides active spec)')
|
|
134
|
+
.option('--json', 'Output raw JSON plan')
|
|
135
|
+
.addHelpText('after', `
|
|
136
|
+
Examples:
|
|
137
|
+
$ specforge plan # Preview plan for active spec
|
|
138
|
+
$ specforge plan --strategy epic-as-team # Force epic-as-team strategy
|
|
139
|
+
$ specforge plan --spec ff1f8edb-4976-458b-acb0 # Plan for a specific spec
|
|
140
|
+
$ specforge plan --json # Output raw JSON for scripting
|
|
141
|
+
|
|
142
|
+
Output shows:
|
|
143
|
+
- Strategy name and reasoning
|
|
144
|
+
- Execution phases with team groupings
|
|
145
|
+
- Ticket-to-worker mapping with dependency indicators
|
|
146
|
+
- [READY] for tickets that can start immediately
|
|
147
|
+
- [BLOCKED] for tickets waiting on dependencies
|
|
148
|
+
|
|
149
|
+
This is a dry-run visualization - it does NOT execute anything.
|
|
150
|
+
Use 'specforge spec activate <specId>' to set the active specification.
|
|
151
|
+
`)
|
|
152
|
+
.action(withErrorHandler(planAction));
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/cli/commands/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Command Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the plan dry-run visualization command
|
|
5
|
+
* that previews Agent Teams implementation plans.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Command line options for plan command
|
|
9
|
+
*/
|
|
10
|
+
export interface PlanOptions {
|
|
11
|
+
/** Output as raw JSON */
|
|
12
|
+
json?: boolean;
|
|
13
|
+
/** Override strategy: epic-as-team | spec-as-team | single-session | auto */
|
|
14
|
+
strategy?: string;
|
|
15
|
+
/** Override specification ID (instead of using active spec) */
|
|
16
|
+
spec?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A single task within a team
|
|
20
|
+
*/
|
|
21
|
+
export interface TaskDefinition {
|
|
22
|
+
ticketId: string;
|
|
23
|
+
title: string;
|
|
24
|
+
slug: string;
|
|
25
|
+
blockedBy: string[];
|
|
26
|
+
estimatedComplexity: string;
|
|
27
|
+
workspace: string | null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A team definition from the implementation plan
|
|
31
|
+
*/
|
|
32
|
+
export interface TeamDefinition {
|
|
33
|
+
name: string;
|
|
34
|
+
epicId: string;
|
|
35
|
+
epicTitle: string;
|
|
36
|
+
suggestedWorkers: number;
|
|
37
|
+
targetWorkspace: string | null;
|
|
38
|
+
canParallelizeWith: string[];
|
|
39
|
+
mustPrecede: string[];
|
|
40
|
+
tasks: TaskDefinition[];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* An execution phase grouping teams
|
|
44
|
+
*/
|
|
45
|
+
export interface ExecutionPhase {
|
|
46
|
+
phase: number;
|
|
47
|
+
teams: string[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Full implementation plan response from the API
|
|
51
|
+
*/
|
|
52
|
+
export interface ImplementationPlan {
|
|
53
|
+
strategy: string;
|
|
54
|
+
reasoning: string;
|
|
55
|
+
teams: TeamDefinition[];
|
|
56
|
+
executionOrder: ExecutionPhase[];
|
|
57
|
+
estimatedTotalTickets: number;
|
|
58
|
+
estimatedParallelizableTickets: number;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=plan.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.types.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/plan.types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,yBAAyB;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,cAAc,EAAE,cAAc,EAAE,CAAC;IACjC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,8BAA8B,EAAE,MAAM,CAAC;CACxC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.types.js","sourceRoot":"","sources":["../../../src/cli/commands/plan.types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec Activate Command
|
|
3
|
+
*
|
|
4
|
+
* Sets or clears the active specification in .specforge.json.
|
|
5
|
+
* The active specification tells Agent Teams which spec to implement.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
/**
|
|
9
|
+
* Activate a specification as the active spec for Agent Teams
|
|
10
|
+
*
|
|
11
|
+
* @param specId Specification ID to activate
|
|
12
|
+
* @param options Command options
|
|
13
|
+
*/
|
|
14
|
+
export declare function specActivateAction(specId: string, options: {
|
|
15
|
+
json?: boolean;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Deactivate the current active specification
|
|
19
|
+
*
|
|
20
|
+
* @param options Command options
|
|
21
|
+
*/
|
|
22
|
+
export declare function specDeactivateAction(options: {
|
|
23
|
+
json?: boolean;
|
|
24
|
+
}): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Register spec activate/deactivate commands with Commander
|
|
27
|
+
*/
|
|
28
|
+
export declare function registerSpecActivateCommand(program: Command): void;
|
|
29
|
+
//# sourceMappingURL=spec-activate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-activate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/spec-activate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CA2Gf;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuClE"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec Activate Command
|
|
3
|
+
*
|
|
4
|
+
* Sets or clears the active specification in .specforge.json.
|
|
5
|
+
* The active specification tells Agent Teams which spec to implement.
|
|
6
|
+
*/
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import { resolveConfig } from '../config/index.js';
|
|
9
|
+
import { setActiveSpecification } from '../config/writer.js';
|
|
10
|
+
import { withErrorHandler, CliError, NetworkError, ValidationError } from '../middleware/error-handler.js';
|
|
11
|
+
import { printBlank, printSuccess, printJson } from '../ui/output.js';
|
|
12
|
+
import { colors } from '../ui/colors.js';
|
|
13
|
+
import { ApiClient } from '../../client/api-client.js';
|
|
14
|
+
/**
|
|
15
|
+
* Activate a specification as the active spec for Agent Teams
|
|
16
|
+
*
|
|
17
|
+
* @param specId Specification ID to activate
|
|
18
|
+
* @param options Command options
|
|
19
|
+
*/
|
|
20
|
+
export async function specActivateAction(specId, options) {
|
|
21
|
+
if (!specId || specId.trim() === '') {
|
|
22
|
+
throw new ValidationError('Specification ID is required', 'Usage: specforge spec activate <specId>');
|
|
23
|
+
}
|
|
24
|
+
const config = resolveConfig();
|
|
25
|
+
if (!config.apiKey) {
|
|
26
|
+
throw new CliError('Not authenticated', 1, 'Run `specforge login` to authenticate first');
|
|
27
|
+
}
|
|
28
|
+
const spinner = ora({
|
|
29
|
+
text: 'Validating specification...',
|
|
30
|
+
color: 'cyan',
|
|
31
|
+
}).start();
|
|
32
|
+
try {
|
|
33
|
+
const client = new ApiClient({
|
|
34
|
+
apiKey: config.apiKey,
|
|
35
|
+
apiUrl: config.apiUrl,
|
|
36
|
+
debug: config.debug,
|
|
37
|
+
});
|
|
38
|
+
// Validate the specification exists
|
|
39
|
+
const spec = await client.call('get_specification', {
|
|
40
|
+
specificationId: specId,
|
|
41
|
+
summary: true,
|
|
42
|
+
});
|
|
43
|
+
if (!spec || !spec.id) {
|
|
44
|
+
spinner.fail('Specification not found');
|
|
45
|
+
throw new CliError(`Specification not found: ${specId}`, 1, "Run 'specforge specs' to list available specifications.");
|
|
46
|
+
}
|
|
47
|
+
// Set active specification in .specforge.json
|
|
48
|
+
spinner.text = 'Setting active specification...';
|
|
49
|
+
setActiveSpecification({
|
|
50
|
+
id: spec.id,
|
|
51
|
+
title: spec.title,
|
|
52
|
+
activatedAt: new Date().toISOString(),
|
|
53
|
+
});
|
|
54
|
+
spinner.succeed(`Active specification set to: ${colors.primary(spec.title)}`);
|
|
55
|
+
if (options.json) {
|
|
56
|
+
printJson({
|
|
57
|
+
action: 'activate',
|
|
58
|
+
specification: {
|
|
59
|
+
id: spec.id,
|
|
60
|
+
title: spec.title,
|
|
61
|
+
status: spec.status,
|
|
62
|
+
epicCount: spec.epicCount,
|
|
63
|
+
ticketCount: spec.ticketCount,
|
|
64
|
+
completedTicketCount: spec.completedTicketCount,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
printBlank();
|
|
70
|
+
console.log(colors.muted(` ID: ${spec.id}`));
|
|
71
|
+
console.log(colors.muted(` Status: ${spec.status}`));
|
|
72
|
+
if (spec.ticketCount !== undefined) {
|
|
73
|
+
const completed = spec.completedTicketCount ?? 0;
|
|
74
|
+
console.log(colors.muted(` Tickets: ${completed}/${spec.ticketCount} completed`));
|
|
75
|
+
}
|
|
76
|
+
printBlank();
|
|
77
|
+
console.log(colors.muted("Run 'specforge status' to see the current context."));
|
|
78
|
+
printBlank();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
if (error instanceof CliError || error instanceof ValidationError) {
|
|
83
|
+
spinner.stop();
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
spinner.fail('Failed to activate specification');
|
|
87
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
88
|
+
if (message.includes('401') || message.includes('Unauthorized')) {
|
|
89
|
+
throw new CliError('Authentication failed', 1, 'Your API key may be invalid. Run `specforge login` to re-authenticate');
|
|
90
|
+
}
|
|
91
|
+
if (message.includes('404') || message.includes('Not Found') || message.includes('not found')) {
|
|
92
|
+
throw new CliError(`Specification not found: ${specId}`, 1, "Run 'specforge specs' to list available specifications.");
|
|
93
|
+
}
|
|
94
|
+
throw new NetworkError(`Failed to activate specification: ${message}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Deactivate the current active specification
|
|
99
|
+
*
|
|
100
|
+
* @param options Command options
|
|
101
|
+
*/
|
|
102
|
+
export async function specDeactivateAction(options) {
|
|
103
|
+
setActiveSpecification(null);
|
|
104
|
+
if (options.json) {
|
|
105
|
+
printJson({ action: 'deactivate', specification: null });
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
printSuccess('Active specification cleared');
|
|
109
|
+
printBlank();
|
|
110
|
+
console.log(colors.muted("No specification is active. Run 'specforge spec activate <specId>' to set one."));
|
|
111
|
+
printBlank();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Register spec activate/deactivate commands with Commander
|
|
116
|
+
*/
|
|
117
|
+
export function registerSpecActivateCommand(program) {
|
|
118
|
+
const spec = program
|
|
119
|
+
.command('spec')
|
|
120
|
+
.description('Manage active specification for Agent Teams');
|
|
121
|
+
spec
|
|
122
|
+
.command('activate <specId>')
|
|
123
|
+
.description('Set active specification for Agent Teams implementation')
|
|
124
|
+
.option('--json', 'Output in JSON format')
|
|
125
|
+
.addHelpText('after', `
|
|
126
|
+
Arguments:
|
|
127
|
+
specId Specification ID to activate
|
|
128
|
+
|
|
129
|
+
Examples:
|
|
130
|
+
$ specforge spec activate ff1f8edb-4976-458b-acb0-b0860cd9a60d
|
|
131
|
+
$ specforge spec activate ff1f8edb --json
|
|
132
|
+
|
|
133
|
+
The active specification is stored in .specforge.json and tells Agent Teams
|
|
134
|
+
which specification to implement when you say "implement the active spec".
|
|
135
|
+
|
|
136
|
+
Use 'specforge specs' to list available specifications.
|
|
137
|
+
Use 'specforge spec deactivate' to clear the active specification.
|
|
138
|
+
`)
|
|
139
|
+
.action(withErrorHandler(specActivateAction));
|
|
140
|
+
spec
|
|
141
|
+
.command('deactivate')
|
|
142
|
+
.description('Clear the active specification')
|
|
143
|
+
.option('--json', 'Output in JSON format')
|
|
144
|
+
.addHelpText('after', `
|
|
145
|
+
Examples:
|
|
146
|
+
$ specforge spec deactivate
|
|
147
|
+
$ specforge spec deactivate --json
|
|
148
|
+
|
|
149
|
+
Removes the activeSpecification section from .specforge.json.
|
|
150
|
+
`)
|
|
151
|
+
.action(withErrorHandler(async (options) => {
|
|
152
|
+
await specDeactivateAction(options);
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=spec-activate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-activate.js","sourceRoot":"","sources":["../../../src/cli/commands/spec-activate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec Activate Command Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the spec activate/deactivate commands
|
|
5
|
+
* that manage the active specification in .specforge.json.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Specification summary from get_specification API (summary mode)
|
|
9
|
+
*/
|
|
10
|
+
export interface SpecificationSummary {
|
|
11
|
+
/** Specification ID */
|
|
12
|
+
id: string;
|
|
13
|
+
/** Specification title */
|
|
14
|
+
title: string;
|
|
15
|
+
/** Current status */
|
|
16
|
+
status: string;
|
|
17
|
+
/** Number of epics */
|
|
18
|
+
epicCount?: number;
|
|
19
|
+
/** Total number of tickets */
|
|
20
|
+
ticketCount?: number;
|
|
21
|
+
/** Number of completed tickets */
|
|
22
|
+
completedTicketCount?: number;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=spec-activate.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-activate.types.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/spec-activate.types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kCAAkC;IAClC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-activate.types.js","sourceRoot":"","sources":["../../../src/cli/commands/spec-activate.types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,OAAO,EACL,aAAa,EAad,MAAM,mBAAmB,CAAC;AAmO3B;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAsIxE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2C5D"}
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import ora from 'ora';
|
|
8
8
|
import { resolveConfig } from '../config/index.js';
|
|
9
|
+
import { loadProjectConfig, getActiveSpecification } from '../config/loader.js';
|
|
9
10
|
import { withErrorHandler, CliError, NetworkError } from '../middleware/error-handler.js';
|
|
10
|
-
import { printBlank } from '../ui/output.js';
|
|
11
|
+
import { printBlank, printWarning } from '../ui/output.js';
|
|
11
12
|
import { colors } from '../ui/colors.js';
|
|
12
13
|
import { ApiClient } from '../../client/api-client.js';
|
|
13
14
|
import { formatTicketNumber, formatDuration, hasWorkingContext, transformApiResponse, transformToDashboardData, calculateSessionProgress, } from './status.types.js';
|
|
@@ -102,6 +103,55 @@ function displayNextActionable(nextActionable) {
|
|
|
102
103
|
console.log(colors.muted(` in ${nextActionable.epicTitle}`));
|
|
103
104
|
}
|
|
104
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Build an ASCII progress bar
|
|
108
|
+
*/
|
|
109
|
+
function buildProgressBar(percent, width = 10) {
|
|
110
|
+
const filled = Math.round((percent / 100) * width);
|
|
111
|
+
const empty = width - filled;
|
|
112
|
+
const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(empty);
|
|
113
|
+
// Color by progress: green >70%, yellow 30-70%, red <30%
|
|
114
|
+
const colorFn = percent > 70 ? colors.success : percent >= 30 ? colors.warning : colors.error;
|
|
115
|
+
return colorFn(`[${bar}]`);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Display Agent Teams progress
|
|
119
|
+
*/
|
|
120
|
+
function displayTeamsProgress(plan) {
|
|
121
|
+
printBlank();
|
|
122
|
+
console.log(colors.bold('Agent Teams Progress'));
|
|
123
|
+
console.log(colors.muted('────────────────────'));
|
|
124
|
+
if (plan.teams.length === 0) {
|
|
125
|
+
console.log(colors.muted('No teams configured for this specification.'));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
// Strategy info
|
|
129
|
+
console.log(`Strategy: ${colors.primary(plan.strategy)}`);
|
|
130
|
+
printBlank();
|
|
131
|
+
// Per-team progress
|
|
132
|
+
for (const team of plan.teams) {
|
|
133
|
+
const total = team.tasks.length;
|
|
134
|
+
// Tasks with no blockers are considered "ready" (approximation of done + ready)
|
|
135
|
+
const blocked = team.tasks.filter(t => t.blockedBy.length > 0).length;
|
|
136
|
+
const ready = total - blocked;
|
|
137
|
+
const percent = total > 0 ? Math.round((ready / total) * 100) : 0;
|
|
138
|
+
const bar = buildProgressBar(percent);
|
|
139
|
+
console.log(` ${colors.bold(team.name)}: ${bar} ${percent}% (${ready}/${total} ready)`);
|
|
140
|
+
// Show blocked tasks
|
|
141
|
+
const blockedTasks = team.tasks.filter(t => t.blockedBy.length > 0);
|
|
142
|
+
for (const task of blockedTasks) {
|
|
143
|
+
const deps = task.blockedBy.join(', ');
|
|
144
|
+
console.log(` ${colors.warning('Blocked')}: ${task.slug} ${colors.muted(`(by ${deps})`)}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Summary
|
|
148
|
+
printBlank();
|
|
149
|
+
const totalTickets = plan.estimatedTotalTickets;
|
|
150
|
+
const parallelizable = plan.estimatedParallelizableTickets;
|
|
151
|
+
console.log(`${colors.bold('Total:')} ${totalTickets} tickets, ` +
|
|
152
|
+
`${parallelizable} parallelizable, ` +
|
|
153
|
+
`${plan.teams.length} team${plan.teams.length === 1 ? '' : 's'}`);
|
|
154
|
+
}
|
|
105
155
|
/**
|
|
106
156
|
* Display status in console format
|
|
107
157
|
*/
|
|
@@ -207,6 +257,36 @@ export async function statusAction(options) {
|
|
|
207
257
|
}
|
|
208
258
|
return;
|
|
209
259
|
}
|
|
260
|
+
// Teams mode
|
|
261
|
+
if (options.teams) {
|
|
262
|
+
// Resolve specification ID
|
|
263
|
+
const projectConfig = loadProjectConfig();
|
|
264
|
+
const activeSpec = getActiveSpecification(projectConfig);
|
|
265
|
+
const specId = activeSpec?.id || config.specificationId;
|
|
266
|
+
if (!specId) {
|
|
267
|
+
spinner.stop();
|
|
268
|
+
printBlank();
|
|
269
|
+
printWarning("No active specification. Run 'specforge spec activate <id>' to set one.");
|
|
270
|
+
printBlank();
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
try {
|
|
274
|
+
const plan = await client.call('get_implementation_plan', { specificationId: specId });
|
|
275
|
+
spinner.stop();
|
|
276
|
+
if (options.json) {
|
|
277
|
+
console.log(JSON.stringify(plan, null, 2));
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
displayTeamsProgress(plan);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
catch (teamsError) {
|
|
284
|
+
spinner.stop();
|
|
285
|
+
const msg = teamsError instanceof Error ? teamsError.message : 'Unknown error';
|
|
286
|
+
throw new NetworkError(`Failed to fetch teams progress: ${msg}`);
|
|
287
|
+
}
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
210
290
|
// Transform API response to status
|
|
211
291
|
const status = transformApiResponse(contextResponse, ticketsResponse);
|
|
212
292
|
// Output based on format
|
|
@@ -237,6 +317,7 @@ export function registerStatusCommand(program) {
|
|
|
237
317
|
.command('status')
|
|
238
318
|
.description('Show current working context and session status')
|
|
239
319
|
.option('-d, --dashboard', 'Show full project dashboard with analytics')
|
|
320
|
+
.option('-t, --teams', 'Show Agent Teams progress')
|
|
240
321
|
.option('--json', 'Output as JSON')
|
|
241
322
|
.option('--toon', 'Output as TOON format')
|
|
242
323
|
.addHelpText('after', `
|
|
@@ -244,6 +325,7 @@ Examples:
|
|
|
244
325
|
$ specforge status # Show current status
|
|
245
326
|
$ specforge status -d # Show full dashboard with analytics
|
|
246
327
|
$ specforge status --dashboard # Show full dashboard with analytics
|
|
328
|
+
$ specforge status --teams # Show Agent Teams progress
|
|
247
329
|
$ specforge status --json # Output as JSON
|
|
248
330
|
$ specforge status --toon # Output as TOON format
|
|
249
331
|
|
|
@@ -252,6 +334,12 @@ Displays:
|
|
|
252
334
|
- Implementation Session: Active session status and statistics
|
|
253
335
|
- Next Actionable: Suggested next ticket to work on
|
|
254
336
|
|
|
337
|
+
Teams View (--teams):
|
|
338
|
+
- Strategy and team structure
|
|
339
|
+
- Per-team progress bars with ticket completion
|
|
340
|
+
- Blocked tickets with dependency reasons
|
|
341
|
+
- Overall ticket and parallelization summary
|
|
342
|
+
|
|
255
343
|
Dashboard View (--dashboard):
|
|
256
344
|
- Overall Progress: Ticket completion with progress bar
|
|
257
345
|
- Time Metrics: Estimated, actual, remaining hours and velocity
|