@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.
Files changed (77) hide show
  1. package/dist/completions/bash-generator.d.ts +13 -0
  2. package/dist/completions/bash-generator.d.ts.map +1 -0
  3. package/dist/completions/bash-generator.js +148 -0
  4. package/dist/completions/bash-generator.js.map +1 -0
  5. package/dist/completions/commands.d.ts +14 -0
  6. package/dist/completions/commands.d.ts.map +1 -0
  7. package/dist/completions/commands.js +114 -0
  8. package/dist/completions/commands.js.map +1 -0
  9. package/dist/completions/fish-generator.d.ts +15 -0
  10. package/dist/completions/fish-generator.d.ts.map +1 -0
  11. package/dist/completions/fish-generator.js +152 -0
  12. package/dist/completions/fish-generator.js.map +1 -0
  13. package/dist/completions/index.d.ts +34 -0
  14. package/dist/completions/index.d.ts.map +1 -0
  15. package/dist/completions/index.js +52 -0
  16. package/dist/completions/index.js.map +1 -0
  17. package/dist/completions/types.d.ts +61 -0
  18. package/dist/completions/types.d.ts.map +1 -0
  19. package/dist/completions/types.js +5 -0
  20. package/dist/completions/types.js.map +1 -0
  21. package/dist/completions/zsh-generator.d.ts +16 -0
  22. package/dist/completions/zsh-generator.d.ts.map +1 -0
  23. package/dist/completions/zsh-generator.js +199 -0
  24. package/dist/completions/zsh-generator.js.map +1 -0
  25. package/dist/configurators/base.d.ts +67 -0
  26. package/dist/configurators/base.d.ts.map +1 -0
  27. package/dist/configurators/base.js +18 -0
  28. package/dist/configurators/base.js.map +1 -0
  29. package/dist/configurators/claude-code.d.ts +16 -0
  30. package/dist/configurators/claude-code.d.ts.map +1 -0
  31. package/dist/configurators/claude-code.js +91 -0
  32. package/dist/configurators/claude-code.js.map +1 -0
  33. package/dist/configurators/cursor.d.ts +17 -0
  34. package/dist/configurators/cursor.d.ts.map +1 -0
  35. package/dist/configurators/cursor.js +140 -0
  36. package/dist/configurators/cursor.js.map +1 -0
  37. package/dist/configurators/detector.d.ts +36 -0
  38. package/dist/configurators/detector.d.ts.map +1 -0
  39. package/dist/configurators/detector.js +131 -0
  40. package/dist/configurators/detector.js.map +1 -0
  41. package/dist/configurators/index.d.ts +17 -0
  42. package/dist/configurators/index.d.ts.map +1 -0
  43. package/dist/configurators/index.js +34 -0
  44. package/dist/configurators/index.js.map +1 -0
  45. package/dist/configurators/registry.d.ts +55 -0
  46. package/dist/configurators/registry.d.ts.map +1 -0
  47. package/dist/configurators/registry.js +82 -0
  48. package/dist/configurators/registry.js.map +1 -0
  49. package/dist/configurators/vscode.d.ts +18 -0
  50. package/dist/configurators/vscode.d.ts.map +1 -0
  51. package/dist/configurators/vscode.js +142 -0
  52. package/dist/configurators/vscode.js.map +1 -0
  53. package/dist/configurators/windsurf.d.ts +17 -0
  54. package/dist/configurators/windsurf.d.ts.map +1 -0
  55. package/dist/configurators/windsurf.js +89 -0
  56. package/dist/configurators/windsurf.js.map +1 -0
  57. package/dist/global-config.d.ts +76 -0
  58. package/dist/global-config.d.ts.map +1 -0
  59. package/dist/global-config.js +212 -0
  60. package/dist/global-config.js.map +1 -0
  61. package/dist/index.d.ts +3 -0
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +6 -0
  64. package/dist/index.js.map +1 -1
  65. package/dist/utils/index.d.ts +2 -0
  66. package/dist/utils/index.d.ts.map +1 -1
  67. package/dist/utils/index.js +2 -0
  68. package/dist/utils/index.js.map +1 -1
  69. package/dist/utils/progress.d.ts +77 -0
  70. package/dist/utils/progress.d.ts.map +1 -0
  71. package/dist/utils/progress.js +83 -0
  72. package/dist/utils/progress.js.map +1 -0
  73. package/dist/utils/task-progress.d.ts +72 -0
  74. package/dist/utils/task-progress.d.ts.map +1 -0
  75. package/dist/utils/task-progress.js +165 -0
  76. package/dist/utils/task-progress.js.map +1 -0
  77. 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":"AAAA;;GAEG;AAkBH;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAAkB,EAClB,UAA8B,EAAE;IAEhC,MAAM,EACJ,KAAK,GAAG,EAAE,EACV,UAAU,GAAG,GAAG,EAChB,SAAS,GAAG,GAAG,EACf,cAAc,GAAG,KAAK,GACvB,GAAG,OAAO,CAAC;IAEZ,kCAAkC;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAE7B,IAAI,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;IAErE,IAAI,cAAc,EAAE,CAAC;QACnB,GAAG,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;IACpC,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CACzC,QAAwB,EACxB,UAA8B,EAAE;IAEhC,MAAM,EAAE,SAAS,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAEtC,IAAI,GAAG,GAAG,iBAAiB,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAE1D,IAAI,SAAS,EAAE,CAAC;QACd,GAAG,IAAI,IAAI,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;IACpD,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAkBD,2CAA2C;AAC3C,MAAM,CAAC,MAAM,cAAc,GAA4B;IACrD,OAAO,EAAE,GAAG;IACZ,UAAU,EAAE,GAAG;IACf,SAAS,EAAE,GAAG;IACd,KAAK,EAAE,GAAG;IACV,OAAO,EAAE,GAAG;IACZ,IAAI,EAAE,GAAG;CACV,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CACvB,KAA0B,EAC1B,UAAyB,EAAE;IAE3B,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAe,EAAE,KAAa;IAChE,OAAO,QAAQ,OAAO,IAAI,KAAK,GAAG,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,UAAkB,EAClB,SAAmB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;IAErE,OAAO,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,OAAgB;IACpE,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,OAAO,GAAG,OAAO,GAAG,IAAI,GAAG,OAAO,EAAE,CAAC;AACvC,CAAC"}
@@ -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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@speclife/core",
3
- "version": "0.9.2",
3
+ "version": "0.10.0",
4
4
  "description": "Core library for SpecLife - adapters and workflows",
5
5
  "repository": {
6
6
  "type": "git",