@speclife/core 0.9.2 → 0.10.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/completions/bash-generator.d.ts +13 -0
- package/dist/completions/bash-generator.d.ts.map +1 -0
- package/dist/completions/bash-generator.js +148 -0
- package/dist/completions/bash-generator.js.map +1 -0
- package/dist/completions/commands.d.ts +14 -0
- package/dist/completions/commands.d.ts.map +1 -0
- package/dist/completions/commands.js +114 -0
- package/dist/completions/commands.js.map +1 -0
- package/dist/completions/fish-generator.d.ts +15 -0
- package/dist/completions/fish-generator.d.ts.map +1 -0
- package/dist/completions/fish-generator.js +152 -0
- package/dist/completions/fish-generator.js.map +1 -0
- package/dist/completions/index.d.ts +34 -0
- package/dist/completions/index.d.ts.map +1 -0
- package/dist/completions/index.js +52 -0
- package/dist/completions/index.js.map +1 -0
- package/dist/completions/types.d.ts +61 -0
- package/dist/completions/types.d.ts.map +1 -0
- package/dist/completions/types.js +5 -0
- package/dist/completions/types.js.map +1 -0
- package/dist/completions/zsh-generator.d.ts +16 -0
- package/dist/completions/zsh-generator.d.ts.map +1 -0
- package/dist/completions/zsh-generator.js +199 -0
- package/dist/completions/zsh-generator.js.map +1 -0
- package/dist/configurators/base.d.ts +67 -0
- package/dist/configurators/base.d.ts.map +1 -0
- package/dist/configurators/base.js +18 -0
- package/dist/configurators/base.js.map +1 -0
- package/dist/configurators/claude-code.d.ts +16 -0
- package/dist/configurators/claude-code.d.ts.map +1 -0
- package/dist/configurators/claude-code.js +91 -0
- package/dist/configurators/claude-code.js.map +1 -0
- package/dist/configurators/cursor.d.ts +17 -0
- package/dist/configurators/cursor.d.ts.map +1 -0
- package/dist/configurators/cursor.js +140 -0
- package/dist/configurators/cursor.js.map +1 -0
- package/dist/configurators/detector.d.ts +36 -0
- package/dist/configurators/detector.d.ts.map +1 -0
- package/dist/configurators/detector.js +131 -0
- package/dist/configurators/detector.js.map +1 -0
- package/dist/configurators/index.d.ts +17 -0
- package/dist/configurators/index.d.ts.map +1 -0
- package/dist/configurators/index.js +34 -0
- package/dist/configurators/index.js.map +1 -0
- package/dist/configurators/registry.d.ts +55 -0
- package/dist/configurators/registry.d.ts.map +1 -0
- package/dist/configurators/registry.js +82 -0
- package/dist/configurators/registry.js.map +1 -0
- package/dist/configurators/vscode.d.ts +18 -0
- package/dist/configurators/vscode.d.ts.map +1 -0
- package/dist/configurators/vscode.js +142 -0
- package/dist/configurators/vscode.js.map +1 -0
- package/dist/configurators/windsurf.d.ts +17 -0
- package/dist/configurators/windsurf.d.ts.map +1 -0
- package/dist/configurators/windsurf.js +89 -0
- package/dist/configurators/windsurf.js.map +1 -0
- package/dist/global-config.d.ts +76 -0
- package/dist/global-config.d.ts.map +1 -0
- package/dist/global-config.js +212 -0
- package/dist/global-config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/progress.d.ts +77 -0
- package/dist/utils/progress.d.ts.map +1 -0
- package/dist/utils/progress.js +83 -0
- package/dist/utils/progress.js.map +1 -0
- package/dist/utils/task-progress.d.ts +72 -0
- package/dist/utils/task-progress.d.ts.map +1 -0
- package/dist/utils/task-progress.js +165 -0
- package/dist/utils/task-progress.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Progress bar utilities for CLI display
|
|
3
|
+
*/
|
|
4
|
+
import type { ChangeProgress } from '../types.js';
|
|
5
|
+
/** Progress bar display options */
|
|
6
|
+
export interface ProgressBarOptions {
|
|
7
|
+
/** Width of the bar in characters (default: 10) */
|
|
8
|
+
width?: number;
|
|
9
|
+
/** Character for filled portion (default: █) */
|
|
10
|
+
filledChar?: string;
|
|
11
|
+
/** Character for empty portion (default: ░) */
|
|
12
|
+
emptyChar?: string;
|
|
13
|
+
/** Include percentage text (default: false) */
|
|
14
|
+
showPercentage?: boolean;
|
|
15
|
+
/** Include count text like "3/5" (default: false) */
|
|
16
|
+
showCount?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a progress bar string from percentage
|
|
20
|
+
* @param percentage Value from 0-100
|
|
21
|
+
* @param options Display options
|
|
22
|
+
* @returns Formatted progress bar string
|
|
23
|
+
*/
|
|
24
|
+
export declare function createProgressBar(percentage: number, options?: ProgressBarOptions): string;
|
|
25
|
+
/**
|
|
26
|
+
* Create a progress bar from ChangeProgress object
|
|
27
|
+
* @param progress Progress info with completed/total
|
|
28
|
+
* @param options Display options
|
|
29
|
+
* @returns Formatted progress bar string
|
|
30
|
+
*/
|
|
31
|
+
export declare function createProgressBarFromChange(progress: ChangeProgress, options?: ProgressBarOptions): string;
|
|
32
|
+
/** Symbol options for different states */
|
|
33
|
+
export interface SymbolOptions {
|
|
34
|
+
/** Symbol for pending/incomplete (default: ○) */
|
|
35
|
+
pending?: string;
|
|
36
|
+
/** Symbol for in-progress (default: ◉) */
|
|
37
|
+
inProgress?: string;
|
|
38
|
+
/** Symbol for completed/success (default: ✓) */
|
|
39
|
+
completed?: string;
|
|
40
|
+
/** Symbol for error/failed (default: ✗) */
|
|
41
|
+
error?: string;
|
|
42
|
+
/** Symbol for warning (default: ⚠) */
|
|
43
|
+
warning?: string;
|
|
44
|
+
/** Symbol for info (default: ℹ) */
|
|
45
|
+
info?: string;
|
|
46
|
+
}
|
|
47
|
+
/** Default symbols for progress display */
|
|
48
|
+
export declare const defaultSymbols: Required<SymbolOptions>;
|
|
49
|
+
/**
|
|
50
|
+
* Get a symbol for a given state
|
|
51
|
+
* @param state State name
|
|
52
|
+
* @param options Custom symbols
|
|
53
|
+
* @returns Symbol character
|
|
54
|
+
*/
|
|
55
|
+
export declare function getSymbol(state: keyof SymbolOptions, options?: SymbolOptions): string;
|
|
56
|
+
/**
|
|
57
|
+
* Format a step indicator for multi-step operations
|
|
58
|
+
* @param current Current step (1-based)
|
|
59
|
+
* @param total Total steps
|
|
60
|
+
* @returns Formatted string like "Step 2/5:"
|
|
61
|
+
*/
|
|
62
|
+
export declare function formatStepIndicator(current: number, total: number): string;
|
|
63
|
+
/**
|
|
64
|
+
* Format a spinner frame (for use with ora or custom spinners)
|
|
65
|
+
* @param frameIndex Current frame index
|
|
66
|
+
* @param frames Array of frames (default: dots)
|
|
67
|
+
* @returns Current frame character
|
|
68
|
+
*/
|
|
69
|
+
export declare function getSpinnerFrame(frameIndex: number, frames?: string[]): string;
|
|
70
|
+
/**
|
|
71
|
+
* Create a simple text-based loading indicator
|
|
72
|
+
* @param message Message to display
|
|
73
|
+
* @param elapsed Elapsed time in ms
|
|
74
|
+
* @returns Formatted loading string
|
|
75
|
+
*/
|
|
76
|
+
export declare function formatLoadingMessage(message: string, elapsed?: number): string;
|
|
77
|
+
//# sourceMappingURL=progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/utils/progress.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,mCAAmC;AACnC,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qDAAqD;IACrD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CAoBR;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,cAAc,EACxB,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CAUR;AAED,0CAA0C;AAC1C,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,2CAA2C;AAC3C,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,aAAa,CAOlD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,aAAa,EAC1B,OAAO,GAAE,aAAkB,GAC1B,MAAM,CAER;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,MAAM,EAAuD,GACpE,MAAM,CAER;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAI9E"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Progress bar utilities for CLI display
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Create a progress bar string from percentage
|
|
6
|
+
* @param percentage Value from 0-100
|
|
7
|
+
* @param options Display options
|
|
8
|
+
* @returns Formatted progress bar string
|
|
9
|
+
*/
|
|
10
|
+
export function createProgressBar(percentage, options = {}) {
|
|
11
|
+
const { width = 10, filledChar = '█', emptyChar = '░', showPercentage = false, } = options;
|
|
12
|
+
// Clamp percentage to valid range
|
|
13
|
+
const clamped = Math.max(0, Math.min(100, percentage));
|
|
14
|
+
const filled = Math.round((clamped / 100) * width);
|
|
15
|
+
const empty = width - filled;
|
|
16
|
+
let bar = `[${filledChar.repeat(filled)}${emptyChar.repeat(empty)}]`;
|
|
17
|
+
if (showPercentage) {
|
|
18
|
+
bar += ` ${Math.round(clamped)}%`;
|
|
19
|
+
}
|
|
20
|
+
return bar;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Create a progress bar from ChangeProgress object
|
|
24
|
+
* @param progress Progress info with completed/total
|
|
25
|
+
* @param options Display options
|
|
26
|
+
* @returns Formatted progress bar string
|
|
27
|
+
*/
|
|
28
|
+
export function createProgressBarFromChange(progress, options = {}) {
|
|
29
|
+
const { showCount = false } = options;
|
|
30
|
+
let bar = createProgressBar(progress.percentage, options);
|
|
31
|
+
if (showCount) {
|
|
32
|
+
bar += ` ${progress.completed}/${progress.total}`;
|
|
33
|
+
}
|
|
34
|
+
return bar;
|
|
35
|
+
}
|
|
36
|
+
/** Default symbols for progress display */
|
|
37
|
+
export const defaultSymbols = {
|
|
38
|
+
pending: '○',
|
|
39
|
+
inProgress: '◉',
|
|
40
|
+
completed: '✓',
|
|
41
|
+
error: '✗',
|
|
42
|
+
warning: '⚠',
|
|
43
|
+
info: 'ℹ',
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Get a symbol for a given state
|
|
47
|
+
* @param state State name
|
|
48
|
+
* @param options Custom symbols
|
|
49
|
+
* @returns Symbol character
|
|
50
|
+
*/
|
|
51
|
+
export function getSymbol(state, options = {}) {
|
|
52
|
+
return options[state] ?? defaultSymbols[state];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Format a step indicator for multi-step operations
|
|
56
|
+
* @param current Current step (1-based)
|
|
57
|
+
* @param total Total steps
|
|
58
|
+
* @returns Formatted string like "Step 2/5:"
|
|
59
|
+
*/
|
|
60
|
+
export function formatStepIndicator(current, total) {
|
|
61
|
+
return `Step ${current}/${total}:`;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Format a spinner frame (for use with ora or custom spinners)
|
|
65
|
+
* @param frameIndex Current frame index
|
|
66
|
+
* @param frames Array of frames (default: dots)
|
|
67
|
+
* @returns Current frame character
|
|
68
|
+
*/
|
|
69
|
+
export function getSpinnerFrame(frameIndex, frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']) {
|
|
70
|
+
return frames[frameIndex % frames.length];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create a simple text-based loading indicator
|
|
74
|
+
* @param message Message to display
|
|
75
|
+
* @param elapsed Elapsed time in ms
|
|
76
|
+
* @returns Formatted loading string
|
|
77
|
+
*/
|
|
78
|
+
export function formatLoadingMessage(message, elapsed) {
|
|
79
|
+
const dots = '.'.repeat((Math.floor(Date.now() / 500) % 3) + 1).padEnd(3);
|
|
80
|
+
const timeStr = elapsed ? ` (${Math.round(elapsed / 1000)}s)` : '';
|
|
81
|
+
return `${message}${dots}${timeStr}`;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/utils/progress.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task progress parsing utilities
|
|
3
|
+
* Parses tasks.md files to extract completion status
|
|
4
|
+
*/
|
|
5
|
+
import type { ChangeProgress, ChangeTask } from '../types.js';
|
|
6
|
+
/** Parsed task with additional metadata */
|
|
7
|
+
export interface ParsedTask extends ChangeTask {
|
|
8
|
+
/** Section number (e.g., "1" from "## 1. Setup") */
|
|
9
|
+
section?: string;
|
|
10
|
+
/** Section name */
|
|
11
|
+
sectionName?: string;
|
|
12
|
+
}
|
|
13
|
+
/** Result of parsing a tasks.md file */
|
|
14
|
+
export interface ParsedTaskFile {
|
|
15
|
+
/** All parsed tasks */
|
|
16
|
+
tasks: ParsedTask[];
|
|
17
|
+
/** Progress summary */
|
|
18
|
+
progress: ChangeProgress;
|
|
19
|
+
/** Tasks grouped by section */
|
|
20
|
+
sections: Map<string, ParsedTask[]>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Parse a single task line
|
|
24
|
+
* @param line Line from tasks.md
|
|
25
|
+
* @param currentSection Current section number
|
|
26
|
+
* @param currentSectionName Current section name
|
|
27
|
+
* @returns Parsed task or null if not a task line
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseTaskLine(line: string, currentSection?: string, currentSectionName?: string): ParsedTask | null;
|
|
30
|
+
/**
|
|
31
|
+
* Parse a section header line
|
|
32
|
+
* @param line Line from tasks.md
|
|
33
|
+
* @returns Section info or null if not a header
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseSectionHeader(line: string): {
|
|
36
|
+
number: string;
|
|
37
|
+
name: string;
|
|
38
|
+
} | null;
|
|
39
|
+
/**
|
|
40
|
+
* Parse tasks.md content into structured data
|
|
41
|
+
* @param content Raw tasks.md content
|
|
42
|
+
* @returns Parsed task file data
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseTasksContent(content: string): ParsedTaskFile;
|
|
45
|
+
/**
|
|
46
|
+
* Load and parse tasks.md from a change directory
|
|
47
|
+
* @param projectRoot Project root path
|
|
48
|
+
* @param specDir Spec directory name (e.g., "openspec")
|
|
49
|
+
* @param changeId Change identifier
|
|
50
|
+
* @returns Parsed task file data
|
|
51
|
+
*/
|
|
52
|
+
export declare function loadTasksFile(projectRoot: string, specDir: string, changeId: string): Promise<ParsedTaskFile>;
|
|
53
|
+
/**
|
|
54
|
+
* Get a summary of tasks by section
|
|
55
|
+
* @param parsed Parsed task file
|
|
56
|
+
* @returns Map of section name to progress
|
|
57
|
+
*/
|
|
58
|
+
export declare function getSectionProgress(parsed: ParsedTaskFile): Map<string, ChangeProgress>;
|
|
59
|
+
/**
|
|
60
|
+
* Find the next uncompleted task
|
|
61
|
+
* @param parsed Parsed task file
|
|
62
|
+
* @returns Next uncompleted task or undefined
|
|
63
|
+
*/
|
|
64
|
+
export declare function getNextTask(parsed: ParsedTaskFile): ParsedTask | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Get tasks by completion status
|
|
67
|
+
* @param parsed Parsed task file
|
|
68
|
+
* @param completed Whether to get completed or pending tasks
|
|
69
|
+
* @returns Filtered tasks
|
|
70
|
+
*/
|
|
71
|
+
export declare function getTasksByStatus(parsed: ParsedTaskFile, completed: boolean): ParsedTask[];
|
|
72
|
+
//# sourceMappingURL=task-progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-progress.d.ts","sourceRoot":"","sources":["../../src/utils/task-progress.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAY9D,2CAA2C;AAC3C,MAAM,WAAW,UAAW,SAAQ,UAAU;IAC5C,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,uBAAuB;IACvB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,uBAAuB;IACvB,QAAQ,EAAE,cAAc,CAAC;IACzB,+BAA+B;IAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;CACrC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,cAAc,CAAC,EAAE,MAAM,EACvB,kBAAkB,CAAC,EAAE,MAAM,GAC1B,UAAU,GAAG,IAAI,CAiCnB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CASxF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAwCjE;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,CAAC,CAczB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAatF;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,UAAU,GAAG,SAAS,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,OAAO,GACjB,UAAU,EAAE,CAEd"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task progress parsing utilities
|
|
3
|
+
* Parses tasks.md files to extract completion status
|
|
4
|
+
*/
|
|
5
|
+
import { readFile } from 'fs/promises';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
/** Regular expressions for parsing task files */
|
|
8
|
+
const TASK_REGEX = {
|
|
9
|
+
/** Matches task line: "- [x] 1.1 Task description" or "- [ ] 1.2 Task description" */
|
|
10
|
+
taskLine: /^[-*]\s*\[([ xX])\]\s*(\d+(?:\.\d+)?)\s+(.+)$/,
|
|
11
|
+
/** Matches section header: "## 1. Section Name" */
|
|
12
|
+
sectionHeader: /^##\s*(\d+)\.\s*(.+)$/,
|
|
13
|
+
/** Matches simple checkbox: "- [x] Task" or "- [ ] Task" */
|
|
14
|
+
simpleCheckbox: /^[-*]\s*\[([ xX])\]\s*(.+)$/,
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Parse a single task line
|
|
18
|
+
* @param line Line from tasks.md
|
|
19
|
+
* @param currentSection Current section number
|
|
20
|
+
* @param currentSectionName Current section name
|
|
21
|
+
* @returns Parsed task or null if not a task line
|
|
22
|
+
*/
|
|
23
|
+
export function parseTaskLine(line, currentSection, currentSectionName) {
|
|
24
|
+
// Try to match numbered task format: "- [x] 1.1 Task description"
|
|
25
|
+
const numberedMatch = line.match(TASK_REGEX.taskLine);
|
|
26
|
+
if (numberedMatch) {
|
|
27
|
+
const [, checkmark, id, content] = numberedMatch;
|
|
28
|
+
return {
|
|
29
|
+
id,
|
|
30
|
+
content: content.trim(),
|
|
31
|
+
completed: checkmark.toLowerCase() === 'x',
|
|
32
|
+
section: currentSection,
|
|
33
|
+
sectionName: currentSectionName,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// Fall back to simple checkbox format: "- [x] Task description"
|
|
37
|
+
const simpleMatch = line.match(TASK_REGEX.simpleCheckbox);
|
|
38
|
+
if (simpleMatch) {
|
|
39
|
+
const [, checkmark, content] = simpleMatch;
|
|
40
|
+
// Generate an ID if in a section, otherwise use content hash
|
|
41
|
+
const id = currentSection
|
|
42
|
+
? `${currentSection}.${Math.random().toString(36).substring(2, 6)}`
|
|
43
|
+
: content.substring(0, 20).toLowerCase().replace(/[^a-z0-9]/g, '-');
|
|
44
|
+
return {
|
|
45
|
+
id,
|
|
46
|
+
content: content.trim(),
|
|
47
|
+
completed: checkmark.toLowerCase() === 'x',
|
|
48
|
+
section: currentSection,
|
|
49
|
+
sectionName: currentSectionName,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Parse a section header line
|
|
56
|
+
* @param line Line from tasks.md
|
|
57
|
+
* @returns Section info or null if not a header
|
|
58
|
+
*/
|
|
59
|
+
export function parseSectionHeader(line) {
|
|
60
|
+
const match = line.match(TASK_REGEX.sectionHeader);
|
|
61
|
+
if (match) {
|
|
62
|
+
return {
|
|
63
|
+
number: match[1],
|
|
64
|
+
name: match[2].trim(),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Parse tasks.md content into structured data
|
|
71
|
+
* @param content Raw tasks.md content
|
|
72
|
+
* @returns Parsed task file data
|
|
73
|
+
*/
|
|
74
|
+
export function parseTasksContent(content) {
|
|
75
|
+
const lines = content.split('\n');
|
|
76
|
+
const tasks = [];
|
|
77
|
+
const sections = new Map();
|
|
78
|
+
let currentSection;
|
|
79
|
+
let currentSectionName;
|
|
80
|
+
for (const line of lines) {
|
|
81
|
+
// Check for section header
|
|
82
|
+
const header = parseSectionHeader(line);
|
|
83
|
+
if (header) {
|
|
84
|
+
currentSection = header.number;
|
|
85
|
+
currentSectionName = header.name;
|
|
86
|
+
if (!sections.has(currentSection)) {
|
|
87
|
+
sections.set(currentSection, []);
|
|
88
|
+
}
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
// Check for task line
|
|
92
|
+
const task = parseTaskLine(line, currentSection, currentSectionName);
|
|
93
|
+
if (task) {
|
|
94
|
+
tasks.push(task);
|
|
95
|
+
if (currentSection && sections.has(currentSection)) {
|
|
96
|
+
sections.get(currentSection).push(task);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Calculate progress
|
|
101
|
+
const completed = tasks.filter(t => t.completed).length;
|
|
102
|
+
const total = tasks.length;
|
|
103
|
+
const percentage = total > 0 ? Math.round((completed / total) * 100) : 0;
|
|
104
|
+
return {
|
|
105
|
+
tasks,
|
|
106
|
+
progress: { completed, total, percentage },
|
|
107
|
+
sections,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Load and parse tasks.md from a change directory
|
|
112
|
+
* @param projectRoot Project root path
|
|
113
|
+
* @param specDir Spec directory name (e.g., "openspec")
|
|
114
|
+
* @param changeId Change identifier
|
|
115
|
+
* @returns Parsed task file data
|
|
116
|
+
*/
|
|
117
|
+
export async function loadTasksFile(projectRoot, specDir, changeId) {
|
|
118
|
+
const tasksPath = join(projectRoot, specDir, 'changes', changeId, 'tasks.md');
|
|
119
|
+
try {
|
|
120
|
+
const content = await readFile(tasksPath, 'utf-8');
|
|
121
|
+
return parseTasksContent(content);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Return empty result if file doesn't exist
|
|
125
|
+
return {
|
|
126
|
+
tasks: [],
|
|
127
|
+
progress: { completed: 0, total: 0, percentage: 0 },
|
|
128
|
+
sections: new Map(),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Get a summary of tasks by section
|
|
134
|
+
* @param parsed Parsed task file
|
|
135
|
+
* @returns Map of section name to progress
|
|
136
|
+
*/
|
|
137
|
+
export function getSectionProgress(parsed) {
|
|
138
|
+
const result = new Map();
|
|
139
|
+
for (const [sectionNum, tasks] of parsed.sections) {
|
|
140
|
+
const sectionName = tasks[0]?.sectionName ?? `Section ${sectionNum}`;
|
|
141
|
+
const completed = tasks.filter(t => t.completed).length;
|
|
142
|
+
const total = tasks.length;
|
|
143
|
+
const percentage = total > 0 ? Math.round((completed / total) * 100) : 0;
|
|
144
|
+
result.set(sectionName, { completed, total, percentage });
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Find the next uncompleted task
|
|
150
|
+
* @param parsed Parsed task file
|
|
151
|
+
* @returns Next uncompleted task or undefined
|
|
152
|
+
*/
|
|
153
|
+
export function getNextTask(parsed) {
|
|
154
|
+
return parsed.tasks.find(t => !t.completed);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get tasks by completion status
|
|
158
|
+
* @param parsed Parsed task file
|
|
159
|
+
* @param completed Whether to get completed or pending tasks
|
|
160
|
+
* @returns Filtered tasks
|
|
161
|
+
*/
|
|
162
|
+
export function getTasksByStatus(parsed, completed) {
|
|
163
|
+
return parsed.tasks.filter(t => t.completed === completed);
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=task-progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-progress.js","sourceRoot":"","sources":["../../src/utils/task-progress.ts"],"names":[],"mappings":"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"}
|