specweave 0.23.10 → 0.23.14
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/.claude-plugin/marketplace.json +7 -7
- package/CLAUDE.md +384 -1449
- package/dist/src/cli/commands/cleanup-cache.d.ts +14 -0
- package/dist/src/cli/commands/cleanup-cache.d.ts.map +1 -0
- package/dist/src/cli/commands/cleanup-cache.js +63 -0
- package/dist/src/cli/commands/cleanup-cache.js.map +1 -0
- package/dist/src/cli/commands/init.js +40 -0
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/helpers/async-project-loader.d.ts +148 -0
- package/dist/src/cli/helpers/async-project-loader.d.ts.map +1 -0
- package/dist/src/cli/helpers/async-project-loader.js +351 -0
- package/dist/src/cli/helpers/async-project-loader.js.map +1 -0
- package/dist/src/cli/helpers/cancelation-handler.d.ts +123 -0
- package/dist/src/cli/helpers/cancelation-handler.d.ts.map +1 -0
- package/dist/src/cli/helpers/cancelation-handler.js +187 -0
- package/dist/src/cli/helpers/cancelation-handler.js.map +1 -0
- package/dist/src/cli/helpers/import-strategy-prompter.d.ts +43 -0
- package/dist/src/cli/helpers/import-strategy-prompter.d.ts.map +1 -0
- package/dist/src/cli/helpers/import-strategy-prompter.js +136 -0
- package/dist/src/cli/helpers/import-strategy-prompter.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado.d.ts +5 -2
- package/dist/src/cli/helpers/issue-tracker/ado.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/ado.js +90 -40
- package/dist/src/cli/helpers/issue-tracker/ado.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/jira.d.ts +2 -1
- package/dist/src/cli/helpers/issue-tracker/jira.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/jira.js +120 -35
- package/dist/src/cli/helpers/issue-tracker/jira.js.map +1 -1
- package/dist/src/cli/helpers/progress-tracker.d.ts +121 -0
- package/dist/src/cli/helpers/progress-tracker.d.ts.map +1 -0
- package/dist/src/cli/helpers/progress-tracker.js +202 -0
- package/dist/src/cli/helpers/progress-tracker.js.map +1 -0
- package/dist/src/cli/helpers/project-count-fetcher.d.ts +69 -0
- package/dist/src/cli/helpers/project-count-fetcher.d.ts.map +1 -0
- package/dist/src/cli/helpers/project-count-fetcher.js +173 -0
- package/dist/src/cli/helpers/project-count-fetcher.js.map +1 -0
- package/dist/src/config/types.d.ts +14 -14
- package/dist/src/core/cache/cache-manager.d.ts +119 -0
- package/dist/src/core/cache/cache-manager.d.ts.map +1 -0
- package/dist/src/core/cache/cache-manager.js +304 -0
- package/dist/src/core/cache/cache-manager.js.map +1 -0
- package/dist/src/core/cache/rate-limit-checker.d.ts +92 -0
- package/dist/src/core/cache/rate-limit-checker.d.ts.map +1 -0
- package/dist/src/core/cache/rate-limit-checker.js +160 -0
- package/dist/src/core/cache/rate-limit-checker.js.map +1 -0
- package/dist/src/core/progress/cancelation-handler.d.ts +79 -0
- package/dist/src/core/progress/cancelation-handler.d.ts.map +1 -0
- package/dist/src/core/progress/cancelation-handler.js +111 -0
- package/dist/src/core/progress/cancelation-handler.js.map +1 -0
- package/dist/src/core/progress/error-logger.d.ts +58 -0
- package/dist/src/core/progress/error-logger.d.ts.map +1 -0
- package/dist/src/core/progress/error-logger.js +99 -0
- package/dist/src/core/progress/error-logger.js.map +1 -0
- package/dist/src/core/progress/import-state.d.ts +71 -0
- package/dist/src/core/progress/import-state.d.ts.map +1 -0
- package/dist/src/core/progress/import-state.js +96 -0
- package/dist/src/core/progress/import-state.js.map +1 -0
- package/dist/src/core/progress/progress-tracker.d.ts +139 -0
- package/dist/src/core/progress/progress-tracker.d.ts.map +1 -0
- package/dist/src/core/progress/progress-tracker.js +223 -0
- package/dist/src/core/progress/progress-tracker.js.map +1 -0
- package/dist/src/init/architecture/types.d.ts +6 -6
- package/dist/src/integrations/ado/ado-client.d.ts +25 -0
- package/dist/src/integrations/ado/ado-client.d.ts.map +1 -1
- package/dist/src/integrations/ado/ado-client.js +67 -0
- package/dist/src/integrations/ado/ado-client.js.map +1 -1
- package/dist/src/integrations/ado/ado-dependency-loader.d.ts +99 -0
- package/dist/src/integrations/ado/ado-dependency-loader.d.ts.map +1 -0
- package/dist/src/integrations/ado/ado-dependency-loader.js +207 -0
- package/dist/src/integrations/ado/ado-dependency-loader.js.map +1 -0
- package/dist/src/integrations/jira/jira-client.d.ts +32 -0
- package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-client.js +81 -0
- package/dist/src/integrations/jira/jira-client.js.map +1 -1
- package/dist/src/integrations/jira/jira-dependency-loader.d.ts +101 -0
- package/dist/src/integrations/jira/jira-dependency-loader.d.ts.map +1 -0
- package/dist/src/integrations/jira/jira-dependency-loader.js +200 -0
- package/dist/src/integrations/jira/jira-dependency-loader.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/.claude-plugin/plugin.json +20 -0
- package/plugins/specweave/agents/architect/AGENT.md +100 -602
- package/plugins/specweave/agents/pm/AGENT.md +96 -597
- package/plugins/specweave/agents/pm/AGENT.md.bak +1893 -0
- package/plugins/specweave/agents/pm/AGENT.md.bak2 +1754 -0
- package/plugins/specweave/commands/check-hooks.md +257 -0
- package/plugins/specweave/hooks/docs-changed.sh +9 -1
- package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
- package/plugins/specweave/hooks/human-input-required.sh +9 -1
- package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
- package/plugins/specweave/hooks/post-edit-spec.sh +202 -31
- package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
- package/plugins/specweave/hooks/post-increment-change.sh +6 -1
- package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
- package/plugins/specweave/hooks/post-increment-completion.sh +6 -1
- package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
- package/plugins/specweave/hooks/post-increment-planning.sh +6 -1
- package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
- package/plugins/specweave/hooks/post-increment-status-change.sh +6 -1
- package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
- package/plugins/specweave/hooks/post-metadata-change.sh +7 -1
- package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
- package/plugins/specweave/hooks/post-task-completion.sh +225 -228
- package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
- package/plugins/specweave/hooks/post-write-spec.sh +207 -31
- package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
- package/plugins/specweave/hooks/pre-edit-spec.sh +151 -0
- package/plugins/specweave/hooks/pre-implementation.sh +9 -1
- package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
- package/plugins/specweave/hooks/pre-task-completion.sh +14 -8
- package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
- package/plugins/specweave/hooks/pre-tool-use.sh +9 -1
- package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
- package/plugins/specweave/hooks/pre-write-spec.sh +151 -0
- package/plugins/specweave/hooks/test-pretooluse-env.sh +72 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
- package/plugins/specweave/skills/compliance-architecture/SKILL.md +374 -0
- package/plugins/specweave/skills/external-sync-wizard/SKILL.md +610 -0
- package/plugins/specweave/skills/pm-closure-validation/SKILL.md +541 -0
- package/plugins/specweave/skills/roadmap-planner/SKILL.md +473 -0
- package/plugins/specweave-ado/commands/refresh-cache.js +25 -0
- package/plugins/specweave-ado/commands/refresh-cache.ts +40 -0
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh +9 -2
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
- package/plugins/specweave-ado/hooks/post-task-completion.sh +10 -2
- package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-github/hooks/post-task-completion.sh +10 -2
- package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
- package/plugins/specweave-jira/commands/refresh-cache.js +25 -0
- package/plugins/specweave-jira/commands/refresh-cache.ts +40 -0
- package/plugins/specweave-jira/hooks/post-task-completion.sh +10 -2
- package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-kafka-streams/commands/topology.md +437 -0
- package/plugins/specweave-n8n/commands/workflow-template.md +262 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +252 -6465
- package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CancelationHandler - Graceful Ctrl+C (SIGINT) handling with state persistence
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Single Ctrl+C: Save state and exit gracefully
|
|
6
|
+
* - Double Ctrl+C (within 2s): Force exit immediately
|
|
7
|
+
* - Polling mechanism for cooperative cancelation
|
|
8
|
+
* - State persistence to resume later
|
|
9
|
+
*
|
|
10
|
+
* @module core/progress/cancelation-handler
|
|
11
|
+
*/
|
|
12
|
+
import { consoleLogger } from '../../utils/logger.js';
|
|
13
|
+
/**
|
|
14
|
+
* CancelationHandler - Handles SIGINT gracefully with double Ctrl+C force exit
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const handler = new CancelationHandler({
|
|
19
|
+
* onSaveState: async () => {
|
|
20
|
+
* await saveImportState();
|
|
21
|
+
* }
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* handler.register();
|
|
25
|
+
*
|
|
26
|
+
* // In import loop
|
|
27
|
+
* for (const project of projects) {
|
|
28
|
+
* if (handler.shouldCancel()) {
|
|
29
|
+
* break;
|
|
30
|
+
* }
|
|
31
|
+
* await importProject(project);
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* handler.unregister();
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export class CancelationHandler {
|
|
38
|
+
constructor(options = {}) {
|
|
39
|
+
this.cancelRequested = false;
|
|
40
|
+
this.firstCtrlCTime = null;
|
|
41
|
+
this.sigintHandler = null;
|
|
42
|
+
this.logger = options.logger ?? consoleLogger;
|
|
43
|
+
this.onSaveState = options.onSaveState;
|
|
44
|
+
this.forceExitTimeout = options.forceExitTimeout ?? 2000;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Register SIGINT listener
|
|
48
|
+
*/
|
|
49
|
+
register() {
|
|
50
|
+
this.sigintHandler = () => {
|
|
51
|
+
void this.handleSigint();
|
|
52
|
+
};
|
|
53
|
+
process.on('SIGINT', this.sigintHandler);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Unregister SIGINT listener
|
|
57
|
+
*/
|
|
58
|
+
unregister() {
|
|
59
|
+
if (this.sigintHandler) {
|
|
60
|
+
process.off('SIGINT', this.sigintHandler);
|
|
61
|
+
this.sigintHandler = null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check if cancelation was requested (polling mechanism)
|
|
66
|
+
*
|
|
67
|
+
* @returns true if Ctrl+C was pressed
|
|
68
|
+
*/
|
|
69
|
+
shouldCancel() {
|
|
70
|
+
return this.cancelRequested;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Handle SIGINT signal (Ctrl+C)
|
|
74
|
+
*/
|
|
75
|
+
async handleSigint() {
|
|
76
|
+
const now = Date.now();
|
|
77
|
+
// Double Ctrl+C detection
|
|
78
|
+
if (this.firstCtrlCTime !== null) {
|
|
79
|
+
const elapsed = now - this.firstCtrlCTime;
|
|
80
|
+
if (elapsed < this.forceExitTimeout) {
|
|
81
|
+
// Force exit on double Ctrl+C
|
|
82
|
+
this.logger.warn('\n⚠️ Forced exit (progress may be lost)');
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// First Ctrl+C
|
|
87
|
+
this.firstCtrlCTime = now;
|
|
88
|
+
this.cancelRequested = true;
|
|
89
|
+
this.logger.log('\n⏸️ Cancelation requested. Saving progress...');
|
|
90
|
+
try {
|
|
91
|
+
// Save state if callback provided
|
|
92
|
+
if (this.onSaveState) {
|
|
93
|
+
await this.onSaveState();
|
|
94
|
+
}
|
|
95
|
+
this.logger.log('✅ Progress saved. Run with --resume to continue.');
|
|
96
|
+
process.exit(0);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
this.logger.error('❌ Failed to save progress:', error);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Reset cancelation state (useful for testing)
|
|
105
|
+
*/
|
|
106
|
+
reset() {
|
|
107
|
+
this.cancelRequested = false;
|
|
108
|
+
this.firstCtrlCTime = null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=cancelation-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancelation-handler.js","sourceRoot":"","sources":["../../../../src/core/progress/cancelation-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AActD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,OAAO,kBAAkB;IAS7B,YAAY,UAA8B,EAAE;QAJpC,oBAAe,GAAY,KAAK,CAAC;QACjC,mBAAc,GAAkB,IAAI,CAAC;QACrC,kBAAa,GAAwB,IAAI,CAAC;QAGhD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC;QAC9C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;IAC3D,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,IAAI,CAAC,aAAa,GAAG,GAAG,EAAE;YACxB,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3B,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;YAC1C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,YAAY;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,0BAA0B;QAC1B,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC;YAC1C,IAAI,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACpC,8BAA8B;gBAC9B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;gBAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAED,eAAe;QACf,IAAI,CAAC,cAAc,GAAG,GAAG,CAAC;QAC1B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAE5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QAEnE,IAAI,CAAC;YACH,kCAAkC;YAClC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YAC3B,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;IAC7B,CAAC;CACF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Logger - Comprehensive error logging for batch operations
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - File-based error logging
|
|
6
|
+
* - Timestamped error records
|
|
7
|
+
* - Structured error format
|
|
8
|
+
* - Automatic log directory creation
|
|
9
|
+
*
|
|
10
|
+
* @module core/progress/error-logger
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Error log entry
|
|
14
|
+
*/
|
|
15
|
+
export interface ErrorLogEntry {
|
|
16
|
+
timestamp: string;
|
|
17
|
+
projectKey: string;
|
|
18
|
+
error: string;
|
|
19
|
+
suggestion?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Error logger options
|
|
23
|
+
*/
|
|
24
|
+
export interface ErrorLoggerOptions {
|
|
25
|
+
/** Log file path (default: .specweave/logs/import-errors.log) */
|
|
26
|
+
logFile?: string;
|
|
27
|
+
/** Project root directory */
|
|
28
|
+
projectRoot?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Log error to file
|
|
32
|
+
*
|
|
33
|
+
* @param projectKey Project identifier
|
|
34
|
+
* @param error Error object or message
|
|
35
|
+
* @param options Logger options
|
|
36
|
+
*/
|
|
37
|
+
export declare function logError(projectKey: string, error: Error | string, options?: ErrorLoggerOptions): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Read error log
|
|
40
|
+
*
|
|
41
|
+
* @param options Logger options
|
|
42
|
+
* @returns Array of error log entries
|
|
43
|
+
*/
|
|
44
|
+
export declare function readErrorLog(options?: ErrorLoggerOptions): Promise<ErrorLogEntry[]>;
|
|
45
|
+
/**
|
|
46
|
+
* Clear error log
|
|
47
|
+
*
|
|
48
|
+
* @param options Logger options
|
|
49
|
+
*/
|
|
50
|
+
export declare function clearErrorLog(options?: ErrorLoggerOptions): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Get error count from log
|
|
53
|
+
*
|
|
54
|
+
* @param options Logger options
|
|
55
|
+
* @returns Number of errors in log
|
|
56
|
+
*/
|
|
57
|
+
export declare function getErrorCount(options?: ErrorLoggerOptions): Promise<number>;
|
|
58
|
+
//# sourceMappingURL=error-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-logger.d.ts","sourceRoot":"","sources":["../../../../src/core/progress/error-logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AASD;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAC5B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,KAAK,GAAG,MAAM,EACrB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CA4B7F;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAOnF;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAGrF"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Logger - Comprehensive error logging for batch operations
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - File-based error logging
|
|
6
|
+
* - Timestamped error records
|
|
7
|
+
* - Structured error format
|
|
8
|
+
* - Automatic log directory creation
|
|
9
|
+
*
|
|
10
|
+
* @module core/progress/error-logger
|
|
11
|
+
*/
|
|
12
|
+
import { promises as fs } from 'fs';
|
|
13
|
+
import { join } from 'path';
|
|
14
|
+
import { existsSync } from 'fs';
|
|
15
|
+
import { mkdirpSync } from '../../utils/fs-native.js';
|
|
16
|
+
/**
|
|
17
|
+
* Get default error log file path
|
|
18
|
+
*/
|
|
19
|
+
function getDefaultLogPath(projectRoot) {
|
|
20
|
+
return join(projectRoot, '.specweave', 'logs', 'import-errors.log');
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Log error to file
|
|
24
|
+
*
|
|
25
|
+
* @param projectKey Project identifier
|
|
26
|
+
* @param error Error object or message
|
|
27
|
+
* @param options Logger options
|
|
28
|
+
*/
|
|
29
|
+
export async function logError(projectKey, error, options = {}) {
|
|
30
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
31
|
+
const logFile = options.logFile ?? getDefaultLogPath(projectRoot);
|
|
32
|
+
const logDir = join(projectRoot, '.specweave', 'logs');
|
|
33
|
+
// Ensure log directory exists
|
|
34
|
+
mkdirpSync(logDir);
|
|
35
|
+
// Create error entry
|
|
36
|
+
const entry = {
|
|
37
|
+
timestamp: new Date().toISOString(),
|
|
38
|
+
projectKey,
|
|
39
|
+
error: error instanceof Error ? error.message : error
|
|
40
|
+
};
|
|
41
|
+
// Format log line
|
|
42
|
+
const logLine = `[${entry.timestamp}] ${entry.projectKey}: ${entry.error}\n`;
|
|
43
|
+
// Append to log file
|
|
44
|
+
await fs.appendFile(logFile, logLine, 'utf-8');
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Read error log
|
|
48
|
+
*
|
|
49
|
+
* @param options Logger options
|
|
50
|
+
* @returns Array of error log entries
|
|
51
|
+
*/
|
|
52
|
+
export async function readErrorLog(options = {}) {
|
|
53
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
54
|
+
const logFile = options.logFile ?? getDefaultLogPath(projectRoot);
|
|
55
|
+
if (!existsSync(logFile)) {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
const content = await fs.readFile(logFile, 'utf-8');
|
|
59
|
+
const lines = content.split('\n').filter(line => line.trim());
|
|
60
|
+
return lines.map(line => {
|
|
61
|
+
// Parse log line: [timestamp] projectKey: error
|
|
62
|
+
const match = line.match(/^\[([^\]]+)\]\s+([^:]+):\s+(.+)$/);
|
|
63
|
+
if (!match) {
|
|
64
|
+
return {
|
|
65
|
+
timestamp: new Date().toISOString(),
|
|
66
|
+
projectKey: 'UNKNOWN',
|
|
67
|
+
error: line
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
timestamp: match[1],
|
|
72
|
+
projectKey: match[2].trim(),
|
|
73
|
+
error: match[3].trim()
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Clear error log
|
|
79
|
+
*
|
|
80
|
+
* @param options Logger options
|
|
81
|
+
*/
|
|
82
|
+
export async function clearErrorLog(options = {}) {
|
|
83
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
84
|
+
const logFile = options.logFile ?? getDefaultLogPath(projectRoot);
|
|
85
|
+
if (existsSync(logFile)) {
|
|
86
|
+
await fs.unlink(logFile);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get error count from log
|
|
91
|
+
*
|
|
92
|
+
* @param options Logger options
|
|
93
|
+
* @returns Number of errors in log
|
|
94
|
+
*/
|
|
95
|
+
export async function getErrorCount(options = {}) {
|
|
96
|
+
const entries = await readErrorLog(options);
|
|
97
|
+
return entries.length;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=error-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-logger.js","sourceRoot":"","sources":["../../../../src/core/progress/error-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ImportState - State persistence for resumable imports
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Save/load import progress
|
|
6
|
+
* - 24-hour TTL for stale state cleanup
|
|
7
|
+
* - Error tracking for retry logic
|
|
8
|
+
*
|
|
9
|
+
* @module core/progress/import-state
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Import error record
|
|
13
|
+
*/
|
|
14
|
+
export interface ImportError {
|
|
15
|
+
/** Item identifier (e.g., project key) */
|
|
16
|
+
id: string;
|
|
17
|
+
/** Error message */
|
|
18
|
+
error: string;
|
|
19
|
+
/** Timestamp when error occurred */
|
|
20
|
+
timestamp: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Import state structure
|
|
24
|
+
*/
|
|
25
|
+
export interface ImportState {
|
|
26
|
+
/** Total number of items to import */
|
|
27
|
+
total: number;
|
|
28
|
+
/** Number of items completed (success + failed) */
|
|
29
|
+
completed: number;
|
|
30
|
+
/** Number of successful imports */
|
|
31
|
+
succeeded: number;
|
|
32
|
+
/** Number of failed imports */
|
|
33
|
+
failed: number;
|
|
34
|
+
/** Array of import errors */
|
|
35
|
+
errors: ImportError[];
|
|
36
|
+
/** Timestamp when state was saved */
|
|
37
|
+
timestamp: number;
|
|
38
|
+
/** Whether import was canceled by user */
|
|
39
|
+
canceled: boolean;
|
|
40
|
+
/** Optional: Last successfully processed item ID */
|
|
41
|
+
lastProcessedId?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Save import state to disk
|
|
45
|
+
*
|
|
46
|
+
* @param state Import state to save
|
|
47
|
+
* @param projectRoot Project root directory
|
|
48
|
+
*/
|
|
49
|
+
export declare function saveImportState(state: ImportState, projectRoot?: string): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Load import state from disk with TTL validation
|
|
52
|
+
*
|
|
53
|
+
* @param projectRoot Project root directory
|
|
54
|
+
* @param ttlMs Time-to-live in milliseconds (default: 24 hours)
|
|
55
|
+
* @returns Import state if valid, null if expired or missing
|
|
56
|
+
*/
|
|
57
|
+
export declare function loadImportState(projectRoot?: string, ttlMs?: number): Promise<ImportState | null>;
|
|
58
|
+
/**
|
|
59
|
+
* Delete import state file
|
|
60
|
+
*
|
|
61
|
+
* @param projectRoot Project root directory
|
|
62
|
+
*/
|
|
63
|
+
export declare function deleteImportState(projectRoot?: string): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Check if import state exists (without loading)
|
|
66
|
+
*
|
|
67
|
+
* @param projectRoot Project root directory
|
|
68
|
+
* @returns true if state file exists
|
|
69
|
+
*/
|
|
70
|
+
export declare function hasImportState(projectRoot?: string): boolean;
|
|
71
|
+
//# sourceMappingURL=import-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-state.d.ts","sourceRoot":"","sources":["../../../../src/core/progress/import-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,0CAA0C;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,QAAQ,EAAE,OAAO,CAAC;IAClB,oDAAoD;IACpD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAYD;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,WAAW,EAClB,WAAW,GAAE,MAAsB,GAClC,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,WAAW,GAAE,MAAsB,EACnC,KAAK,GAAE,MAA4B,GAClC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA0B7B;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,GAAE,MAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAM1F;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,WAAW,GAAE,MAAsB,GAAG,OAAO,CAG3E"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ImportState - State persistence for resumable imports
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Save/load import progress
|
|
6
|
+
* - 24-hour TTL for stale state cleanup
|
|
7
|
+
* - Error tracking for retry logic
|
|
8
|
+
*
|
|
9
|
+
* @module core/progress/import-state
|
|
10
|
+
*/
|
|
11
|
+
import { promises as fs } from 'fs';
|
|
12
|
+
import { join } from 'path';
|
|
13
|
+
import { existsSync } from 'fs';
|
|
14
|
+
import { mkdirpSync } from '../../utils/fs-native.js';
|
|
15
|
+
/**
|
|
16
|
+
* Get import state file path
|
|
17
|
+
*
|
|
18
|
+
* @param projectRoot Project root directory
|
|
19
|
+
* @returns Path to import-state.json
|
|
20
|
+
*/
|
|
21
|
+
function getStateFilePath(projectRoot = process.cwd()) {
|
|
22
|
+
return join(projectRoot, '.specweave', 'cache', 'import-state.json');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Save import state to disk
|
|
26
|
+
*
|
|
27
|
+
* @param state Import state to save
|
|
28
|
+
* @param projectRoot Project root directory
|
|
29
|
+
*/
|
|
30
|
+
export async function saveImportState(state, projectRoot = process.cwd()) {
|
|
31
|
+
const stateFilePath = getStateFilePath(projectRoot);
|
|
32
|
+
const cacheDir = join(projectRoot, '.specweave', 'cache');
|
|
33
|
+
// Ensure cache directory exists
|
|
34
|
+
mkdirpSync(cacheDir);
|
|
35
|
+
// Add timestamp
|
|
36
|
+
const stateWithTimestamp = {
|
|
37
|
+
...state,
|
|
38
|
+
timestamp: Date.now(),
|
|
39
|
+
};
|
|
40
|
+
// Write to file
|
|
41
|
+
await fs.writeFile(stateFilePath, JSON.stringify(stateWithTimestamp, null, 2), 'utf-8');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Load import state from disk with TTL validation
|
|
45
|
+
*
|
|
46
|
+
* @param projectRoot Project root directory
|
|
47
|
+
* @param ttlMs Time-to-live in milliseconds (default: 24 hours)
|
|
48
|
+
* @returns Import state if valid, null if expired or missing
|
|
49
|
+
*/
|
|
50
|
+
export async function loadImportState(projectRoot = process.cwd(), ttlMs = 24 * 60 * 60 * 1000 // 24 hours
|
|
51
|
+
) {
|
|
52
|
+
const stateFilePath = getStateFilePath(projectRoot);
|
|
53
|
+
// Check if file exists
|
|
54
|
+
if (!existsSync(stateFilePath)) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
// Read and parse file
|
|
59
|
+
const content = await fs.readFile(stateFilePath, 'utf-8');
|
|
60
|
+
const state = JSON.parse(content);
|
|
61
|
+
// Validate TTL
|
|
62
|
+
const age = Date.now() - state.timestamp;
|
|
63
|
+
if (age > ttlMs) {
|
|
64
|
+
// State is expired, delete it
|
|
65
|
+
await deleteImportState(projectRoot);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return state;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
// Invalid JSON or read error
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Delete import state file
|
|
77
|
+
*
|
|
78
|
+
* @param projectRoot Project root directory
|
|
79
|
+
*/
|
|
80
|
+
export async function deleteImportState(projectRoot = process.cwd()) {
|
|
81
|
+
const stateFilePath = getStateFilePath(projectRoot);
|
|
82
|
+
if (existsSync(stateFilePath)) {
|
|
83
|
+
await fs.unlink(stateFilePath);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if import state exists (without loading)
|
|
88
|
+
*
|
|
89
|
+
* @param projectRoot Project root directory
|
|
90
|
+
* @returns true if state file exists
|
|
91
|
+
*/
|
|
92
|
+
export function hasImportState(projectRoot = process.cwd()) {
|
|
93
|
+
const stateFilePath = getStateFilePath(projectRoot);
|
|
94
|
+
return existsSync(stateFilePath);
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=import-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-state.js","sourceRoot":"","sources":["../../../../src/core/progress/import-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAoCtD;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,cAAsB,OAAO,CAAC,GAAG,EAAE;IAC3D,OAAO,IAAI,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC;AACvE,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAkB,EAClB,cAAsB,OAAO,CAAC,GAAG,EAAE;IAEnC,MAAM,aAAa,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IAE1D,gCAAgC;IAChC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAErB,gBAAgB;IAChB,MAAM,kBAAkB,GAAgB;QACtC,GAAG,KAAK;QACR,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACtB,CAAC;IAEF,gBAAgB;IAChB,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC1F,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,cAAsB,OAAO,CAAC,GAAG,EAAE,EACnC,QAAgB,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW;;IAE/C,MAAM,aAAa,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAEpD,uBAAuB;IACvB,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,sBAAsB;QACtB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAE/C,eAAe;QACf,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC;QACzC,IAAI,GAAG,GAAG,KAAK,EAAE,CAAC;YAChB,8BAA8B;YAC9B,MAAM,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACrC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,6BAA6B;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,cAAsB,OAAO,CAAC,GAAG,EAAE;IACzE,MAAM,aAAa,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAEpD,IAAI,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9B,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,cAAsB,OAAO,CAAC,GAAG,EAAE;IAChE,MAAM,aAAa,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACpD,OAAO,UAAU,CAAC,aAAa,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProgressTracker - Real-time progress tracking with ETA calculation
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - ASCII progress bar (30 characters)
|
|
6
|
+
* - Linear ETA extrapolation
|
|
7
|
+
* - Elapsed time tracking
|
|
8
|
+
* - Project-level status display (✅ ❌ ⏳)
|
|
9
|
+
* - Configurable update frequency
|
|
10
|
+
*
|
|
11
|
+
* @module core/progress/progress-tracker
|
|
12
|
+
*/
|
|
13
|
+
import { Logger } from '../../utils/logger.js';
|
|
14
|
+
/**
|
|
15
|
+
* Item status types
|
|
16
|
+
*/
|
|
17
|
+
export type ItemStatus = 'pending' | 'success' | 'error';
|
|
18
|
+
/**
|
|
19
|
+
* Progress tracker options
|
|
20
|
+
*/
|
|
21
|
+
export interface ProgressTrackerOptions {
|
|
22
|
+
/** Total number of items to process */
|
|
23
|
+
total: number;
|
|
24
|
+
/** Label for the operation (e.g., "Importing projects") */
|
|
25
|
+
label: string;
|
|
26
|
+
/** Show ETA calculation */
|
|
27
|
+
showEta?: boolean;
|
|
28
|
+
/** Update frequency (update every N items, default: 5) */
|
|
29
|
+
updateFrequency?: number;
|
|
30
|
+
/** Logger instance */
|
|
31
|
+
logger?: Logger;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Item with status
|
|
35
|
+
*/
|
|
36
|
+
interface TrackedItem {
|
|
37
|
+
name: string;
|
|
38
|
+
status: ItemStatus;
|
|
39
|
+
timestamp: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* ProgressTracker - Real-time progress tracking with ASCII progress bar and ETA
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const tracker = new ProgressTracker({
|
|
47
|
+
* total: 127,
|
|
48
|
+
* label: 'Importing projects',
|
|
49
|
+
* showEta: true,
|
|
50
|
+
* updateFrequency: 5
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
53
|
+
* for (const project of projects) {
|
|
54
|
+
* await importProject(project);
|
|
55
|
+
* tracker.update(project.key, 'success');
|
|
56
|
+
* }
|
|
57
|
+
*
|
|
58
|
+
* tracker.finish(120, 5, 2);
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare class ProgressTracker {
|
|
62
|
+
private total;
|
|
63
|
+
private label;
|
|
64
|
+
private showEta;
|
|
65
|
+
private updateFrequency;
|
|
66
|
+
private logger;
|
|
67
|
+
private items;
|
|
68
|
+
private startTime;
|
|
69
|
+
private lastUpdateCount;
|
|
70
|
+
constructor(options: ProgressTrackerOptions);
|
|
71
|
+
/**
|
|
72
|
+
* Update progress for a specific item
|
|
73
|
+
*
|
|
74
|
+
* @param itemName Item identifier (e.g., project key)
|
|
75
|
+
* @param status Item status (pending, success, error)
|
|
76
|
+
*/
|
|
77
|
+
update(itemName: string, status: ItemStatus): void;
|
|
78
|
+
/**
|
|
79
|
+
* Finish progress tracking and show final summary
|
|
80
|
+
*
|
|
81
|
+
* @param succeeded Count of successful items
|
|
82
|
+
* @param failed Count of failed items
|
|
83
|
+
* @param skipped Count of skipped items
|
|
84
|
+
*/
|
|
85
|
+
finish(succeeded: number, failed: number, skipped: number): void;
|
|
86
|
+
/**
|
|
87
|
+
* Render progress bar to console
|
|
88
|
+
*/
|
|
89
|
+
private render;
|
|
90
|
+
/**
|
|
91
|
+
* Render ASCII progress bar
|
|
92
|
+
*
|
|
93
|
+
* @param percentage Completion percentage (0-100)
|
|
94
|
+
* @returns ASCII progress bar (30 characters)
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* renderProgressBar(0) => "[> ]"
|
|
98
|
+
* renderProgressBar(37) => "[==========> ]"
|
|
99
|
+
* renderProgressBar(100) => "[==============================]"
|
|
100
|
+
*/
|
|
101
|
+
renderProgressBar(percentage: number): string;
|
|
102
|
+
/**
|
|
103
|
+
* Get elapsed time in human-readable format
|
|
104
|
+
*
|
|
105
|
+
* @returns Elapsed time string (e.g., "2m 34s", "45s")
|
|
106
|
+
*/
|
|
107
|
+
getElapsedTime(): string;
|
|
108
|
+
/**
|
|
109
|
+
* Get estimated time remaining (ETA) using linear extrapolation
|
|
110
|
+
*
|
|
111
|
+
* Formula: ETA = (total - completed) * (elapsed / completed)
|
|
112
|
+
*
|
|
113
|
+
* @returns ETA string (e.g., ", ~2m remaining", ", ~45s remaining")
|
|
114
|
+
*/
|
|
115
|
+
getEta(): string;
|
|
116
|
+
/**
|
|
117
|
+
* Get count of completed items (success + error)
|
|
118
|
+
*/
|
|
119
|
+
private getCompletedCount;
|
|
120
|
+
/**
|
|
121
|
+
* Get items by status
|
|
122
|
+
*/
|
|
123
|
+
getItemsByStatus(status: ItemStatus): TrackedItem[];
|
|
124
|
+
/**
|
|
125
|
+
* Get current progress statistics
|
|
126
|
+
*/
|
|
127
|
+
getStats(): {
|
|
128
|
+
total: number;
|
|
129
|
+
completed: number;
|
|
130
|
+
succeeded: number;
|
|
131
|
+
failed: number;
|
|
132
|
+
pending: number;
|
|
133
|
+
percentage: number;
|
|
134
|
+
elapsedMs: number;
|
|
135
|
+
etaMs: number | null;
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
export {};
|
|
139
|
+
//# sourceMappingURL=progress-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress-tracker.d.ts","sourceRoot":"","sources":["../../../../src/core/progress/progress-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,EAAiB,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAa;gBAExB,OAAO,EAAE,sBAAsB;IAS3C;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAoBlD;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAgBhE;;OAEG;IACH,OAAO,CAAC,MAAM;IAcd;;;;;;;;;;OAUG;IACH,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAuB7C;;;;OAIG;IACH,cAAc,IAAI,MAAM;IAaxB;;;;;;OAMG;IACH,MAAM,IAAI,MAAM;IAyBhB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAUzB;;OAEG;IACH,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,EAAE;IAUnD;;OAEG;IACH,QAAQ,IAAI;QACV,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB;CA0BF"}
|