specweave 0.22.14 → 0.23.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/CLAUDE.md +178 -1
- package/dist/src/cli/commands/import-external.d.ts +22 -0
- package/dist/src/cli/commands/import-external.d.ts.map +1 -0
- package/dist/src/cli/commands/import-external.js +282 -0
- package/dist/src/cli/commands/import-external.js.map +1 -0
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +46 -0
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/helpers/github-repo-selector.d.ts +59 -0
- package/dist/src/cli/helpers/github-repo-selector.d.ts.map +1 -0
- package/dist/src/cli/helpers/github-repo-selector.js +265 -0
- package/dist/src/cli/helpers/github-repo-selector.js.map +1 -0
- package/dist/src/config/types.d.ts +16 -16
- package/dist/src/core/increment/ac-status-manager.d.ts.map +1 -1
- package/dist/src/core/increment/ac-status-manager.js +4 -2
- package/dist/src/core/increment/ac-status-manager.js.map +1 -1
- package/dist/src/core/increment/completion-validator.d.ts +30 -1
- package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
- package/dist/src/core/increment/completion-validator.js +151 -3
- package/dist/src/core/increment/completion-validator.js.map +1 -1
- package/dist/src/core/increment/increment-archiver.d.ts +25 -0
- package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
- package/dist/src/core/increment/increment-archiver.js +130 -3
- package/dist/src/core/increment/increment-archiver.js.map +1 -1
- package/dist/src/core/living-docs/feature-archiver.d.ts +37 -0
- package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -1
- package/dist/src/core/living-docs/feature-archiver.js +262 -18
- package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
- package/dist/src/core/living-docs/feature-id-manager.d.ts +17 -0
- package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -1
- package/dist/src/core/living-docs/feature-id-manager.js +25 -0
- package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.d.ts +14 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +46 -0
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/sync/sync-event-logger.d.ts +15 -1
- package/dist/src/core/sync/sync-event-logger.d.ts.map +1 -1
- package/dist/src/core/sync/sync-event-logger.js +39 -1
- package/dist/src/core/sync/sync-event-logger.js.map +1 -1
- package/dist/src/core/types/sync-config-validator.d.ts +57 -0
- package/dist/src/core/types/sync-config-validator.d.ts.map +1 -0
- package/dist/src/core/types/sync-config-validator.js +116 -0
- package/dist/src/core/types/sync-config-validator.js.map +1 -0
- package/dist/src/importers/duplicate-detector.d.ts +107 -0
- package/dist/src/importers/duplicate-detector.d.ts.map +1 -0
- package/dist/src/importers/duplicate-detector.js +189 -0
- package/dist/src/importers/duplicate-detector.js.map +1 -0
- package/dist/src/importers/import-coordinator.d.ts +15 -0
- package/dist/src/importers/import-coordinator.d.ts.map +1 -1
- package/dist/src/importers/import-coordinator.js +43 -1
- package/dist/src/importers/import-coordinator.js.map +1 -1
- package/dist/src/importers/item-converter.d.ts +5 -0
- package/dist/src/importers/item-converter.d.ts.map +1 -1
- package/dist/src/importers/item-converter.js +27 -2
- package/dist/src/importers/item-converter.js.map +1 -1
- package/dist/src/importers/rate-limiter.d.ts +128 -0
- package/dist/src/importers/rate-limiter.d.ts.map +1 -0
- package/dist/src/importers/rate-limiter.js +200 -0
- package/dist/src/importers/rate-limiter.js.map +1 -0
- package/dist/src/init/compliance/types.d.ts +2 -2
- package/dist/src/integrations/ado/ado-client.d.ts +6 -0
- package/dist/src/integrations/ado/ado-client.d.ts.map +1 -1
- package/dist/src/integrations/ado/ado-client.js +23 -0
- package/dist/src/integrations/ado/ado-client.js.map +1 -1
- package/dist/src/integrations/jira/jira-client.d.ts +6 -0
- package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-client.js +38 -0
- package/dist/src/integrations/jira/jira-client.js.map +1 -1
- package/dist/src/sync/external-item-sync-service.d.ts +150 -0
- package/dist/src/sync/external-item-sync-service.d.ts.map +1 -0
- package/dist/src/sync/external-item-sync-service.js +241 -0
- package/dist/src/sync/external-item-sync-service.js.map +1 -0
- package/dist/src/sync/format-preservation-sync.d.ts +90 -0
- package/dist/src/sync/format-preservation-sync.d.ts.map +1 -0
- package/dist/src/sync/format-preservation-sync.js +173 -0
- package/dist/src/sync/format-preservation-sync.js.map +1 -0
- package/dist/src/sync/index.d.ts +8 -0
- package/dist/src/sync/index.d.ts.map +1 -0
- package/dist/src/sync/index.js +6 -0
- package/dist/src/sync/index.js.map +1 -0
- package/dist/src/sync/sync-coordinator.d.ts +49 -0
- package/dist/src/sync/sync-coordinator.d.ts.map +1 -0
- package/dist/src/sync/sync-coordinator.js +248 -0
- package/dist/src/sync/sync-coordinator.js.map +1 -0
- package/dist/src/sync/sync-metadata.d.ts +75 -0
- package/dist/src/sync/sync-metadata.d.ts.map +1 -0
- package/dist/src/sync/sync-metadata.js +100 -0
- package/dist/src/sync/sync-metadata.js.map +1 -0
- package/dist/src/types/living-docs-us-file.d.ts +63 -0
- package/dist/src/types/living-docs-us-file.d.ts.map +1 -0
- package/dist/src/types/living-docs-us-file.js +27 -0
- package/dist/src/types/living-docs-us-file.js.map +1 -0
- package/dist/src/validators/format-preservation-validator.d.ts +127 -0
- package/dist/src/validators/format-preservation-validator.d.ts.map +1 -0
- package/dist/src/validators/format-preservation-validator.js +187 -0
- package/dist/src/validators/format-preservation-validator.js.map +1 -0
- package/package.json +3 -2
- package/plugins/specweave/.claude-plugin/plugin.json +20 -0
- package/plugins/specweave/commands/specweave-archive-features.md +11 -1
- package/plugins/specweave/commands/specweave-import-docs.md +88 -278
- package/plugins/specweave/commands/specweave-import-external.md +407 -0
- package/plugins/specweave/hooks/post-edit-spec.sh +41 -0
- package/plugins/specweave/hooks/post-increment-completion.sh +0 -0
- package/plugins/specweave/hooks/post-spec-update.sh +0 -0
- package/plugins/specweave/hooks/post-task-completion.sh +13 -3
- package/plugins/specweave/hooks/post-write-spec.sh +37 -0
- package/plugins/specweave/lib/hooks/auto-transition.js +1 -1
- package/plugins/specweave/lib/hooks/auto-transition.ts +1 -1
- package/plugins/specweave/lib/hooks/invoke-translator-skill.js +1 -1
- package/plugins/specweave/lib/hooks/invoke-translator-skill.ts +1 -1
- package/plugins/specweave/lib/hooks/sync-living-docs.js +35 -1
- package/plugins/specweave/lib/hooks/sync-us-tasks.js +179 -3
- package/plugins/specweave/lib/hooks/translate-file.js +1 -1
- package/plugins/specweave/lib/hooks/translate-file.ts +1 -1
- package/plugins/specweave/lib/hooks/update-ac-status.js +1 -1
- package/plugins/specweave/lib/hooks/update-ac-status.ts +1 -1
- package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.d.ts +115 -0
- package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js +345 -0
- package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.d.ts +106 -0
- package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js +220 -0
- package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.d.ts +60 -0
- package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js +192 -0
- package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.d.ts +52 -0
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +276 -0
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.d.ts +163 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +541 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +157 -0
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.js +191 -0
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.js.map +1 -0
- package/plugins/specweave/lib/vendor/generators/spec/task-parser.d.ts +95 -0
- package/plugins/specweave/lib/vendor/generators/spec/task-parser.js +301 -0
- package/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -0
- package/plugins/specweave/lib/vendor/utils/logger.d.ts +48 -0
- package/plugins/specweave/lib/vendor/utils/logger.js +53 -0
- package/plugins/specweave/lib/vendor/utils/logger.js.map +1 -0
- package/plugins/specweave/lib/vendor/utils/translation.d.ts +187 -0
- package/plugins/specweave/lib/vendor/utils/translation.js +414 -0
- package/plugins/specweave/lib/vendor/utils/translation.js.map +1 -0
- package/plugins/specweave-ado/lib/ado-multi-project-sync.js +0 -1
- package/plugins/specweave-github/commands/specweave-github-update-user-story.md +1 -1
- package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +1 -1
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -170
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -5694
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"active-increment-manager.js","sourceRoot":"","sources":["../../../../src/core/increment/active-increment-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-Transition Manager
|
|
3
|
+
*
|
|
4
|
+
* Automatically transitions increment status based on lifecycle events:
|
|
5
|
+
* - spec.md created → BACKLOG → PLANNING
|
|
6
|
+
* - tasks.md created → PLANNING/BACKLOG → ACTIVE
|
|
7
|
+
* - first task started → PLANNING → ACTIVE
|
|
8
|
+
*
|
|
9
|
+
* Part of increment 0039: Ultra-Smart Next Command
|
|
10
|
+
*/
|
|
11
|
+
import { IncrementStatus } from '../types/increment-metadata.js';
|
|
12
|
+
export interface TransitionEvent {
|
|
13
|
+
incrementId: string;
|
|
14
|
+
from: IncrementStatus;
|
|
15
|
+
to: IncrementStatus;
|
|
16
|
+
trigger: 'spec-created' | 'tasks-created' | 'task-started' | 'auto-correct';
|
|
17
|
+
timestamp: string;
|
|
18
|
+
}
|
|
19
|
+
export interface AutoTransitionResult {
|
|
20
|
+
transitioned: boolean;
|
|
21
|
+
from?: IncrementStatus;
|
|
22
|
+
to?: IncrementStatus;
|
|
23
|
+
reason: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Manages automatic status transitions based on increment artifacts
|
|
27
|
+
*/
|
|
28
|
+
export declare class AutoTransitionManager {
|
|
29
|
+
private projectRoot;
|
|
30
|
+
constructor(projectRoot: string);
|
|
31
|
+
/**
|
|
32
|
+
* Handle spec.md creation event
|
|
33
|
+
* BACKLOG → PLANNING
|
|
34
|
+
*/
|
|
35
|
+
handleSpecCreated(incrementId: string): Promise<AutoTransitionResult>;
|
|
36
|
+
/**
|
|
37
|
+
* Handle tasks.md creation event
|
|
38
|
+
* PLANNING/BACKLOG → ACTIVE
|
|
39
|
+
*/
|
|
40
|
+
handleTasksCreated(incrementId: string): Promise<AutoTransitionResult>;
|
|
41
|
+
/**
|
|
42
|
+
* Handle first task started event
|
|
43
|
+
* PLANNING → ACTIVE
|
|
44
|
+
*/
|
|
45
|
+
handleTaskStarted(incrementId: string): Promise<AutoTransitionResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Detect increment phase based on artifacts (spec.md, plan.md, tasks.md)
|
|
48
|
+
*/
|
|
49
|
+
detectPhase(incrementId: string): Promise<IncrementStatus>;
|
|
50
|
+
/**
|
|
51
|
+
* Auto-correct status based on artifacts
|
|
52
|
+
* Useful for fixing increments with invalid "planned"/"planning" statuses
|
|
53
|
+
*/
|
|
54
|
+
autoCorrect(incrementId: string, force?: boolean): Promise<AutoTransitionResult>;
|
|
55
|
+
/**
|
|
56
|
+
* Get transition event for logging
|
|
57
|
+
*/
|
|
58
|
+
createTransitionEvent(incrementId: string, from: IncrementStatus, to: IncrementStatus, trigger: TransitionEvent['trigger']): TransitionEvent;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=auto-transition-manager.d.ts.map
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-Transition Manager
|
|
3
|
+
*
|
|
4
|
+
* Automatically transitions increment status based on lifecycle events:
|
|
5
|
+
* - spec.md created → BACKLOG → PLANNING
|
|
6
|
+
* - tasks.md created → PLANNING/BACKLOG → ACTIVE
|
|
7
|
+
* - first task started → PLANNING → ACTIVE
|
|
8
|
+
*
|
|
9
|
+
* Part of increment 0039: Ultra-Smart Next Command
|
|
10
|
+
*/
|
|
11
|
+
import { IncrementStatus, validateTransition } from '../types/increment-metadata.js';
|
|
12
|
+
import { MetadataManager } from './metadata-manager.js';
|
|
13
|
+
import * as fs from 'fs';
|
|
14
|
+
import * as path from 'path';
|
|
15
|
+
/**
|
|
16
|
+
* Manages automatic status transitions based on increment artifacts
|
|
17
|
+
*/
|
|
18
|
+
export class AutoTransitionManager {
|
|
19
|
+
constructor(projectRoot) {
|
|
20
|
+
this.projectRoot = projectRoot;
|
|
21
|
+
// Note: MetadataManager uses process.cwd() internally
|
|
22
|
+
// In production, this manager should be instantiated from the project root
|
|
23
|
+
// In tests, we use integration tests with real file system
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Handle spec.md creation event
|
|
27
|
+
* BACKLOG → PLANNING
|
|
28
|
+
*/
|
|
29
|
+
async handleSpecCreated(incrementId) {
|
|
30
|
+
try {
|
|
31
|
+
const metadata = MetadataManager.read(incrementId);
|
|
32
|
+
// Only transition from BACKLOG to PLANNING
|
|
33
|
+
if (metadata.status === IncrementStatus.BACKLOG) {
|
|
34
|
+
validateTransition(metadata.status, IncrementStatus.PLANNING);
|
|
35
|
+
MetadataManager.updateStatus(incrementId, IncrementStatus.PLANNING);
|
|
36
|
+
return {
|
|
37
|
+
transitioned: true,
|
|
38
|
+
from: IncrementStatus.BACKLOG,
|
|
39
|
+
to: IncrementStatus.PLANNING,
|
|
40
|
+
reason: 'spec.md created - planning phase started'
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
transitioned: false,
|
|
45
|
+
reason: `Already in ${metadata.status} - no transition needed`
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
return {
|
|
50
|
+
transitioned: false,
|
|
51
|
+
reason: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Handle tasks.md creation event
|
|
57
|
+
* PLANNING/BACKLOG → ACTIVE
|
|
58
|
+
*/
|
|
59
|
+
async handleTasksCreated(incrementId) {
|
|
60
|
+
try {
|
|
61
|
+
const metadata = MetadataManager.read(incrementId);
|
|
62
|
+
// Transition to ACTIVE from PLANNING or BACKLOG
|
|
63
|
+
if (metadata.status === IncrementStatus.PLANNING || metadata.status === IncrementStatus.BACKLOG) {
|
|
64
|
+
const from = metadata.status;
|
|
65
|
+
validateTransition(from, IncrementStatus.ACTIVE);
|
|
66
|
+
MetadataManager.updateStatus(incrementId, IncrementStatus.ACTIVE);
|
|
67
|
+
return {
|
|
68
|
+
transitioned: true,
|
|
69
|
+
from,
|
|
70
|
+
to: IncrementStatus.ACTIVE,
|
|
71
|
+
reason: 'tasks.md created - execution phase started'
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
transitioned: false,
|
|
76
|
+
reason: `Already in ${metadata.status} - no transition needed`
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
return {
|
|
81
|
+
transitioned: false,
|
|
82
|
+
reason: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Handle first task started event
|
|
88
|
+
* PLANNING → ACTIVE
|
|
89
|
+
*/
|
|
90
|
+
async handleTaskStarted(incrementId) {
|
|
91
|
+
try {
|
|
92
|
+
const metadata = MetadataManager.read(incrementId);
|
|
93
|
+
// Force transition to ACTIVE if still in PLANNING
|
|
94
|
+
if (metadata.status === IncrementStatus.PLANNING) {
|
|
95
|
+
validateTransition(metadata.status, IncrementStatus.ACTIVE);
|
|
96
|
+
MetadataManager.updateStatus(incrementId, IncrementStatus.ACTIVE);
|
|
97
|
+
return {
|
|
98
|
+
transitioned: true,
|
|
99
|
+
from: IncrementStatus.PLANNING,
|
|
100
|
+
to: IncrementStatus.ACTIVE,
|
|
101
|
+
reason: 'task execution started - moved to active'
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
transitioned: false,
|
|
106
|
+
reason: `Already in ${metadata.status} - no transition needed`
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
return {
|
|
111
|
+
transitioned: false,
|
|
112
|
+
reason: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Detect increment phase based on artifacts (spec.md, plan.md, tasks.md)
|
|
118
|
+
*/
|
|
119
|
+
async detectPhase(incrementId) {
|
|
120
|
+
const incrementPath = path.join(this.projectRoot, '.specweave/increments', incrementId);
|
|
121
|
+
const hasSpec = fs.existsSync(path.join(incrementPath, 'spec.md'));
|
|
122
|
+
const hasPlan = fs.existsSync(path.join(incrementPath, 'plan.md'));
|
|
123
|
+
const hasTasks = fs.existsSync(path.join(incrementPath, 'tasks.md'));
|
|
124
|
+
// Artifact-based phase detection
|
|
125
|
+
if (hasTasks) {
|
|
126
|
+
return IncrementStatus.ACTIVE; // Tasks exist → execution phase
|
|
127
|
+
}
|
|
128
|
+
else if (hasSpec || hasPlan) {
|
|
129
|
+
return IncrementStatus.PLANNING; // Spec/plan exist → planning phase
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
return IncrementStatus.BACKLOG; // Nothing exists → backlog
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Auto-correct status based on artifacts
|
|
137
|
+
* Useful for fixing increments with invalid "planned"/"planning" statuses
|
|
138
|
+
*/
|
|
139
|
+
async autoCorrect(incrementId, force = false) {
|
|
140
|
+
try {
|
|
141
|
+
const metadata = MetadataManager.read(incrementId);
|
|
142
|
+
const detectedPhase = await this.detectPhase(incrementId);
|
|
143
|
+
// Check for status mismatch
|
|
144
|
+
if (metadata.status !== detectedPhase) {
|
|
145
|
+
// Validate transition is allowed
|
|
146
|
+
try {
|
|
147
|
+
validateTransition(metadata.status, detectedPhase);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
if (!force) {
|
|
151
|
+
return {
|
|
152
|
+
transitioned: false,
|
|
153
|
+
reason: `Cannot auto-correct: ${error instanceof Error ? error.message : String(error)}`
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// Force mode: skip validation
|
|
157
|
+
}
|
|
158
|
+
const from = metadata.status;
|
|
159
|
+
MetadataManager.updateStatus(incrementId, detectedPhase);
|
|
160
|
+
return {
|
|
161
|
+
transitioned: true,
|
|
162
|
+
from,
|
|
163
|
+
to: detectedPhase,
|
|
164
|
+
reason: `Auto-corrected based on artifacts (${force ? 'forced' : 'validated'})`
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
transitioned: false,
|
|
169
|
+
reason: `Status already correct (${metadata.status})`
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
return {
|
|
174
|
+
transitioned: false,
|
|
175
|
+
reason: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get transition event for logging
|
|
181
|
+
*/
|
|
182
|
+
createTransitionEvent(incrementId, from, to, trigger) {
|
|
183
|
+
return {
|
|
184
|
+
incrementId,
|
|
185
|
+
from,
|
|
186
|
+
to,
|
|
187
|
+
trigger,
|
|
188
|
+
timestamp: new Date().toISOString()
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=auto-transition-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-transition-manager.js","sourceRoot":"","sources":["../../../../src/core/increment/auto-transition-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Duplicate Detector - Scan filesystem and detect duplicate increments
|
|
3
|
+
*
|
|
4
|
+
* Detects increments that exist in multiple locations (active, archive, abandoned)
|
|
5
|
+
* or have the same increment number with different names.
|
|
6
|
+
*
|
|
7
|
+
* Part of increment 0033: Duplicate Increment Prevention System
|
|
8
|
+
*/
|
|
9
|
+
import { IncrementStatus } from '../types/increment-metadata.js';
|
|
10
|
+
/**
|
|
11
|
+
* Report of all duplicates found
|
|
12
|
+
*/
|
|
13
|
+
export interface DuplicateReport {
|
|
14
|
+
duplicates: Duplicate[];
|
|
15
|
+
totalChecked: number;
|
|
16
|
+
duplicateCount: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A duplicate increment (same number in multiple locations or with different names)
|
|
20
|
+
*/
|
|
21
|
+
export interface Duplicate {
|
|
22
|
+
incrementNumber: string;
|
|
23
|
+
locations: IncrementLocation[];
|
|
24
|
+
recommendedWinner: IncrementLocation;
|
|
25
|
+
losingVersions: IncrementLocation[];
|
|
26
|
+
resolutionReason: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Information about an increment location
|
|
30
|
+
*/
|
|
31
|
+
export interface IncrementLocation {
|
|
32
|
+
path: string;
|
|
33
|
+
name: string;
|
|
34
|
+
status: IncrementStatus;
|
|
35
|
+
lastActivity: string;
|
|
36
|
+
fileCount: number;
|
|
37
|
+
totalSize: number;
|
|
38
|
+
hasReports: boolean;
|
|
39
|
+
hasGitHubLink: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Scan all increment folders and detect duplicates
|
|
43
|
+
*/
|
|
44
|
+
export declare function detectAllDuplicates(rootDir: string): Promise<DuplicateReport>;
|
|
45
|
+
/**
|
|
46
|
+
* Detect duplicates for a specific increment number
|
|
47
|
+
*
|
|
48
|
+
* Returns ALL increments that have the given number, even if there's only one.
|
|
49
|
+
* This is used for validation before creating a new increment.
|
|
50
|
+
*/
|
|
51
|
+
export declare function detectDuplicatesByNumber(incrementNumber: string, rootDir: string): Promise<IncrementLocation[]>;
|
|
52
|
+
//# sourceMappingURL=duplicate-detector.d.ts.map
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Duplicate Detector - Scan filesystem and detect duplicate increments
|
|
3
|
+
*
|
|
4
|
+
* Detects increments that exist in multiple locations (active, archive, abandoned)
|
|
5
|
+
* or have the same increment number with different names.
|
|
6
|
+
*
|
|
7
|
+
* Part of increment 0033: Duplicate Increment Prevention System
|
|
8
|
+
*/
|
|
9
|
+
import fs from 'fs-extra';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
import { glob } from 'glob';
|
|
12
|
+
/**
|
|
13
|
+
* Scan all increment folders and detect duplicates
|
|
14
|
+
*/
|
|
15
|
+
export async function detectAllDuplicates(rootDir) {
|
|
16
|
+
const incrementsDir = path.join(rootDir, '.specweave', 'increments');
|
|
17
|
+
// Check if increments directory exists
|
|
18
|
+
if (!await fs.pathExists(incrementsDir)) {
|
|
19
|
+
return {
|
|
20
|
+
duplicates: [],
|
|
21
|
+
totalChecked: 0,
|
|
22
|
+
duplicateCount: 0
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
// Scan all locations in parallel
|
|
26
|
+
const [active, archived, abandoned] = await Promise.all([
|
|
27
|
+
scanDirectory(incrementsDir, false),
|
|
28
|
+
scanDirectory(path.join(incrementsDir, '_archive'), false),
|
|
29
|
+
scanDirectory(path.join(incrementsDir, '_abandoned'), false)
|
|
30
|
+
]);
|
|
31
|
+
// Group by increment number
|
|
32
|
+
const byNumber = new Map();
|
|
33
|
+
const allIncrements = [...active, ...archived, ...abandoned];
|
|
34
|
+
for (const inc of allIncrements) {
|
|
35
|
+
const number = extractIncrementNumber(inc.name);
|
|
36
|
+
if (!number)
|
|
37
|
+
continue; // Skip non-increment folders
|
|
38
|
+
if (!byNumber.has(number)) {
|
|
39
|
+
byNumber.set(number, []);
|
|
40
|
+
}
|
|
41
|
+
byNumber.get(number).push(inc);
|
|
42
|
+
}
|
|
43
|
+
// Find duplicates (increment number exists in >1 location or >1 name)
|
|
44
|
+
const duplicates = [];
|
|
45
|
+
byNumber.forEach((locations, number) => {
|
|
46
|
+
if (locations.length > 1) {
|
|
47
|
+
// Duplicate found!
|
|
48
|
+
const winner = selectWinner(locations);
|
|
49
|
+
duplicates.push({
|
|
50
|
+
incrementNumber: number,
|
|
51
|
+
locations,
|
|
52
|
+
recommendedWinner: winner,
|
|
53
|
+
losingVersions: locations.filter(l => l !== winner),
|
|
54
|
+
resolutionReason: explainWinner(winner, locations)
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return {
|
|
59
|
+
duplicates,
|
|
60
|
+
totalChecked: allIncrements.length,
|
|
61
|
+
duplicateCount: duplicates.length
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Detect duplicates for a specific increment number
|
|
66
|
+
*
|
|
67
|
+
* Returns ALL increments that have the given number, even if there's only one.
|
|
68
|
+
* This is used for validation before creating a new increment.
|
|
69
|
+
*/
|
|
70
|
+
export async function detectDuplicatesByNumber(incrementNumber, rootDir) {
|
|
71
|
+
const incrementsDir = path.join(rootDir, '.specweave', 'increments');
|
|
72
|
+
// Check if increments directory exists
|
|
73
|
+
if (!await fs.pathExists(incrementsDir)) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
// Normalize increment number (pad to 4 digits)
|
|
77
|
+
const normalizedNumber = incrementNumber.padStart(4, '0');
|
|
78
|
+
// Scan all locations in parallel
|
|
79
|
+
const [active, archived, abandoned] = await Promise.all([
|
|
80
|
+
scanDirectory(incrementsDir, false),
|
|
81
|
+
scanDirectory(path.join(incrementsDir, '_archive'), false),
|
|
82
|
+
scanDirectory(path.join(incrementsDir, '_abandoned'), false)
|
|
83
|
+
]);
|
|
84
|
+
// Combine all increments and filter by number
|
|
85
|
+
const allIncrements = [...active, ...archived, ...abandoned];
|
|
86
|
+
const matchingIncrements = allIncrements.filter(inc => {
|
|
87
|
+
const number = extractIncrementNumber(inc.name);
|
|
88
|
+
return number === normalizedNumber;
|
|
89
|
+
});
|
|
90
|
+
return matchingIncrements;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Scan a directory for increment folders
|
|
94
|
+
*/
|
|
95
|
+
async function scanDirectory(dir, throwOnError = false) {
|
|
96
|
+
try {
|
|
97
|
+
// Check if directory exists
|
|
98
|
+
if (!await fs.pathExists(dir)) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
// Find all directories matching increment pattern (####-*)
|
|
102
|
+
const pattern = path.join(dir, '[0-9][0-9][0-9][0-9]-*');
|
|
103
|
+
const allPaths = await glob(pattern);
|
|
104
|
+
const locations = [];
|
|
105
|
+
for (const incPath of allPaths) {
|
|
106
|
+
try {
|
|
107
|
+
const stats = await fs.stat(incPath);
|
|
108
|
+
if (!stats.isDirectory())
|
|
109
|
+
continue;
|
|
110
|
+
const name = path.basename(incPath);
|
|
111
|
+
// Skip nested .specweave folders
|
|
112
|
+
if (incPath.includes('.specweave/increments/.specweave')) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
// Read metadata
|
|
116
|
+
const metadataPath = path.join(incPath, 'metadata.json');
|
|
117
|
+
let metadata = {
|
|
118
|
+
status: 'unknown',
|
|
119
|
+
lastActivity: new Date(stats.mtime).toISOString()
|
|
120
|
+
};
|
|
121
|
+
if (await fs.pathExists(metadataPath)) {
|
|
122
|
+
try {
|
|
123
|
+
metadata = await fs.readJson(metadataPath);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
// Skip corrupted metadata (will be caught by validation)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Count files recursively
|
|
130
|
+
const allFiles = await glob(path.join(incPath, '**/*'));
|
|
131
|
+
const fileCount = allFiles.filter(async (f) => {
|
|
132
|
+
try {
|
|
133
|
+
const fstats = await fs.stat(f);
|
|
134
|
+
return fstats.isFile();
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}).length;
|
|
140
|
+
// Calculate total size
|
|
141
|
+
let totalSize = 0;
|
|
142
|
+
for (const file of allFiles) {
|
|
143
|
+
try {
|
|
144
|
+
const fstats = await fs.stat(file);
|
|
145
|
+
if (fstats.isFile()) {
|
|
146
|
+
totalSize += fstats.size;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// Skip files we can't read
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Check for reports folder
|
|
154
|
+
const reportsDir = path.join(incPath, 'reports');
|
|
155
|
+
const hasReports = await fs.pathExists(reportsDir);
|
|
156
|
+
// Check for GitHub link in metadata
|
|
157
|
+
const hasGitHubLink = metadata.github && metadata.github.issue;
|
|
158
|
+
locations.push({
|
|
159
|
+
path: incPath,
|
|
160
|
+
name,
|
|
161
|
+
status: metadata.status || 'unknown',
|
|
162
|
+
lastActivity: metadata.lastActivity || new Date(stats.mtime).toISOString(),
|
|
163
|
+
fileCount,
|
|
164
|
+
totalSize,
|
|
165
|
+
hasReports,
|
|
166
|
+
hasGitHubLink
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
// Skip increments we can't read
|
|
171
|
+
if (throwOnError)
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return locations;
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
if (throwOnError)
|
|
179
|
+
throw error;
|
|
180
|
+
return [];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Extract increment number from increment name (e.g., "0001-feature" → "0001")
|
|
185
|
+
*/
|
|
186
|
+
function extractIncrementNumber(name) {
|
|
187
|
+
const match = name.match(/^(\d{4})-/);
|
|
188
|
+
return match ? match[1] : null;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Select winning version based on priority rules
|
|
192
|
+
*/
|
|
193
|
+
function selectWinner(locations) {
|
|
194
|
+
// Priority 1: Active status > Completed > Paused > Backlog > Abandoned
|
|
195
|
+
const statusPriority = {
|
|
196
|
+
active: 5,
|
|
197
|
+
completed: 4,
|
|
198
|
+
paused: 3,
|
|
199
|
+
backlog: 2,
|
|
200
|
+
abandoned: 1,
|
|
201
|
+
unknown: 0
|
|
202
|
+
};
|
|
203
|
+
// Sort by priority
|
|
204
|
+
const sorted = [...locations].sort((a, b) => {
|
|
205
|
+
// 1. Status priority
|
|
206
|
+
const aPriority = statusPriority[a.status] || 0;
|
|
207
|
+
const bPriority = statusPriority[b.status] || 0;
|
|
208
|
+
if (bPriority !== aPriority)
|
|
209
|
+
return bPriority - aPriority;
|
|
210
|
+
// 2. Most recent activity
|
|
211
|
+
const aTime = new Date(a.lastActivity).getTime();
|
|
212
|
+
const bTime = new Date(b.lastActivity).getTime();
|
|
213
|
+
if (bTime !== aTime)
|
|
214
|
+
return bTime - aTime;
|
|
215
|
+
// 3. Most complete (more files)
|
|
216
|
+
if (b.fileCount !== a.fileCount)
|
|
217
|
+
return b.fileCount - a.fileCount;
|
|
218
|
+
// 4. Location preference (active > _archive > _abandoned)
|
|
219
|
+
const locationScore = (loc) => {
|
|
220
|
+
if (loc.path.includes('_abandoned'))
|
|
221
|
+
return 1;
|
|
222
|
+
if (loc.path.includes('_archive'))
|
|
223
|
+
return 2;
|
|
224
|
+
return 3; // active
|
|
225
|
+
};
|
|
226
|
+
return locationScore(b) - locationScore(a);
|
|
227
|
+
});
|
|
228
|
+
return sorted[0];
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Explain why this version won
|
|
232
|
+
*/
|
|
233
|
+
function explainWinner(winner, all) {
|
|
234
|
+
const reasons = [];
|
|
235
|
+
const statusPriority = {
|
|
236
|
+
active: 5,
|
|
237
|
+
completed: 4,
|
|
238
|
+
paused: 3,
|
|
239
|
+
backlog: 2,
|
|
240
|
+
abandoned: 1,
|
|
241
|
+
unknown: 0
|
|
242
|
+
};
|
|
243
|
+
// Check status
|
|
244
|
+
const winnerStatusPriority = statusPriority[winner.status] || 0;
|
|
245
|
+
const hasLowerStatus = all.some(loc => loc !== winner && (statusPriority[loc.status] || 0) < winnerStatusPriority);
|
|
246
|
+
if (hasLowerStatus) {
|
|
247
|
+
reasons.push(`Higher status (${winner.status})`);
|
|
248
|
+
}
|
|
249
|
+
// Check recency
|
|
250
|
+
const winnerTime = new Date(winner.lastActivity).getTime();
|
|
251
|
+
const hasOlderActivity = all.some(loc => loc !== winner && new Date(loc.lastActivity).getTime() < winnerTime);
|
|
252
|
+
if (hasOlderActivity) {
|
|
253
|
+
const date = new Date(winner.lastActivity).toISOString().split('T')[0];
|
|
254
|
+
reasons.push(`Most recent activity (${date})`);
|
|
255
|
+
}
|
|
256
|
+
// Check completeness
|
|
257
|
+
const hasFewerFiles = all.some(loc => loc !== winner && loc.fileCount < winner.fileCount);
|
|
258
|
+
if (hasFewerFiles) {
|
|
259
|
+
reasons.push(`Most complete (${winner.fileCount} files)`);
|
|
260
|
+
}
|
|
261
|
+
// Check location
|
|
262
|
+
const winnerLocation = winner.path.includes('_abandoned') ? 'abandoned' :
|
|
263
|
+
winner.path.includes('_archive') ? 'archive' : 'active';
|
|
264
|
+
const hasWorseLocation = all.some(loc => {
|
|
265
|
+
const locLocation = loc.path.includes('_abandoned') ? 'abandoned' :
|
|
266
|
+
loc.path.includes('_archive') ? 'archive' : 'active';
|
|
267
|
+
const locationPriority = { active: 3, archive: 2, abandoned: 1 };
|
|
268
|
+
return locationPriority[locLocation] <
|
|
269
|
+
locationPriority[winnerLocation];
|
|
270
|
+
});
|
|
271
|
+
if (hasWorseLocation) {
|
|
272
|
+
reasons.push(`In ${winnerLocation} location`);
|
|
273
|
+
}
|
|
274
|
+
return reasons.length > 0 ? reasons.join(', ') : 'Default selection';
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=duplicate-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate-detector.js","sourceRoot":"","sources":["../../../../src/core/increment/duplicate-detector.ts"],"names":[],"mappings":"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"}
|