specweave 0.24.8 → 0.24.9

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 (130) hide show
  1. package/dist/src/cli/commands/init.d.ts.map +1 -1
  2. package/dist/src/cli/commands/init.js +3 -1
  3. package/dist/src/cli/commands/init.js.map +1 -1
  4. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.d.ts.map +1 -1
  5. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js +18 -2
  6. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js.map +1 -1
  7. package/dist/src/core/repo-structure/git-error-handler.d.ts +1 -1
  8. package/dist/src/core/repo-structure/git-error-handler.d.ts.map +1 -1
  9. package/dist/src/core/repo-structure/git-provider.d.ts +1 -1
  10. package/dist/src/core/repo-structure/git-provider.d.ts.map +1 -1
  11. package/dist/src/core/repo-structure/platform-registry.d.ts.map +1 -1
  12. package/dist/src/core/repo-structure/platform-registry.js +20 -9
  13. package/dist/src/core/repo-structure/platform-registry.js.map +1 -1
  14. package/dist/src/core/repo-structure/prompt-consolidator.d.ts +13 -1
  15. package/dist/src/core/repo-structure/prompt-consolidator.d.ts.map +1 -1
  16. package/dist/src/core/repo-structure/prompt-consolidator.js +38 -5
  17. package/dist/src/core/repo-structure/prompt-consolidator.js.map +1 -1
  18. package/dist/src/core/repo-structure/providers/azure-devops-provider.d.ts +64 -0
  19. package/dist/src/core/repo-structure/providers/azure-devops-provider.d.ts.map +1 -0
  20. package/dist/src/core/repo-structure/providers/azure-devops-provider.js +263 -0
  21. package/dist/src/core/repo-structure/providers/azure-devops-provider.js.map +1 -0
  22. package/dist/src/core/repo-structure/providers/bitbucket-provider.d.ts +12 -11
  23. package/dist/src/core/repo-structure/providers/bitbucket-provider.d.ts.map +1 -1
  24. package/dist/src/core/repo-structure/providers/bitbucket-provider.js +164 -30
  25. package/dist/src/core/repo-structure/providers/bitbucket-provider.js.map +1 -1
  26. package/dist/src/core/repo-structure/providers/gitlab-provider.d.ts +10 -9
  27. package/dist/src/core/repo-structure/providers/gitlab-provider.d.ts.map +1 -1
  28. package/dist/src/core/repo-structure/providers/gitlab-provider.js +182 -28
  29. package/dist/src/core/repo-structure/providers/gitlab-provider.js.map +1 -1
  30. package/dist/src/core/repo-structure/providers/index.d.ts +3 -1
  31. package/dist/src/core/repo-structure/providers/index.d.ts.map +1 -1
  32. package/dist/src/core/repo-structure/providers/index.js +10 -2
  33. package/dist/src/core/repo-structure/providers/index.js.map +1 -1
  34. package/dist/src/core/repo-structure/providers/local-provider.d.ts +61 -0
  35. package/dist/src/core/repo-structure/providers/local-provider.d.ts.map +1 -0
  36. package/dist/src/core/repo-structure/providers/local-provider.js +148 -0
  37. package/dist/src/core/repo-structure/providers/local-provider.js.map +1 -0
  38. package/dist/src/core/repo-structure/repo-structure-manager.d.ts +11 -1
  39. package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
  40. package/dist/src/core/repo-structure/repo-structure-manager.js +268 -84
  41. package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
  42. package/package.json +1 -1
  43. package/plugins/specweave/agents/pm/AGENT.md.bak +1893 -0
  44. package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
  45. package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
  46. package/plugins/specweave/hooks/lib/migrate-increment-work.sh.bak +245 -0
  47. package/plugins/specweave/hooks/lib/sync-spec-content.sh.bak +149 -0
  48. package/plugins/specweave/hooks/lib/validate-spec-status.sh.bak +163 -0
  49. package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
  50. package/plugins/specweave/hooks/post-first-increment.sh.bak +61 -0
  51. package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
  52. package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
  53. package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
  54. package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
  55. package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
  56. package/plugins/specweave/hooks/post-spec-update.sh.bak +158 -0
  57. package/plugins/specweave/hooks/post-task-completion.sh +69 -175
  58. package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
  59. package/plugins/specweave/hooks/post-user-story-complete.sh.bak +179 -0
  60. package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
  61. package/plugins/specweave/hooks/pre-command-deduplication.sh.bak +83 -0
  62. package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
  63. package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
  64. package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
  65. package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
  66. package/plugins/specweave/hooks/user-prompt-submit.sh.bak +386 -0
  67. package/plugins/specweave/lib/hooks/auto-transition.js.bak +50 -0
  68. package/plugins/specweave/lib/hooks/auto-transition.ts.bak +84 -0
  69. package/plugins/specweave/lib/hooks/consolidated-sync.js +183 -0
  70. package/plugins/specweave/lib/hooks/git-diff-analyzer.d.js.bak +0 -0
  71. package/plugins/specweave/lib/hooks/git-diff-analyzer.d.ts.bak +89 -0
  72. package/plugins/specweave/lib/hooks/git-diff-analyzer.js.bak +142 -0
  73. package/plugins/specweave/lib/hooks/git-diff-analyzer.ts.bak +269 -0
  74. package/plugins/specweave/lib/hooks/invoke-translator-skill.d.js.bak +0 -0
  75. package/plugins/specweave/lib/hooks/invoke-translator-skill.d.ts.bak +60 -0
  76. package/plugins/specweave/lib/hooks/invoke-translator-skill.js.bak +155 -0
  77. package/plugins/specweave/lib/hooks/invoke-translator-skill.ts.bak +264 -0
  78. package/plugins/specweave/lib/hooks/prepare-reflection-context.d.js.bak +0 -0
  79. package/plugins/specweave/lib/hooks/prepare-reflection-context.d.ts.bak +42 -0
  80. package/plugins/specweave/lib/hooks/prepare-reflection-context.js.bak +110 -0
  81. package/plugins/specweave/lib/hooks/prepare-reflection-context.ts.bak +178 -0
  82. package/plugins/specweave/lib/hooks/reflection-config-loader.d.js.bak +0 -0
  83. package/plugins/specweave/lib/hooks/reflection-config-loader.d.ts.bak +45 -0
  84. package/plugins/specweave/lib/hooks/reflection-config-loader.js.bak +92 -0
  85. package/plugins/specweave/lib/hooks/reflection-config-loader.ts.bak +156 -0
  86. package/plugins/specweave/lib/hooks/reflection-parser.d.js.bak +0 -0
  87. package/plugins/specweave/lib/hooks/reflection-parser.d.ts.bak +33 -0
  88. package/plugins/specweave/lib/hooks/reflection-parser.js.bak +301 -0
  89. package/plugins/specweave/lib/hooks/reflection-parser.ts.bak +484 -0
  90. package/plugins/specweave/lib/hooks/reflection-prompt-builder.d.js.bak +0 -0
  91. package/plugins/specweave/lib/hooks/reflection-prompt-builder.d.ts.bak +56 -0
  92. package/plugins/specweave/lib/hooks/reflection-prompt-builder.js.bak +182 -0
  93. package/plugins/specweave/lib/hooks/reflection-prompt-builder.ts.bak +306 -0
  94. package/plugins/specweave/lib/hooks/reflection-storage.d.js.bak +0 -0
  95. package/plugins/specweave/lib/hooks/reflection-storage.d.ts.bak +64 -0
  96. package/plugins/specweave/lib/hooks/reflection-storage.js.bak +231 -0
  97. package/plugins/specweave/lib/hooks/reflection-storage.ts.bak +369 -0
  98. package/plugins/specweave/lib/hooks/run-self-reflection.d.js.bak +0 -0
  99. package/plugins/specweave/lib/hooks/run-self-reflection.d.ts.bak +43 -0
  100. package/plugins/specweave/lib/hooks/run-self-reflection.js.bak +132 -0
  101. package/plugins/specweave/lib/hooks/run-self-reflection.ts.bak +258 -0
  102. package/plugins/specweave/lib/hooks/sync-cache.js.bak +294 -0
  103. package/plugins/specweave/lib/hooks/sync-living-docs.d.js.bak +1 -0
  104. package/plugins/specweave/lib/hooks/sync-living-docs.d.ts.bak +27 -0
  105. package/plugins/specweave/lib/hooks/sync-living-docs.js.bak +339 -0
  106. package/plugins/specweave/lib/hooks/sync-us-tasks.js.bak +476 -0
  107. package/plugins/specweave/lib/hooks/translate-file.d.js.bak +0 -0
  108. package/plugins/specweave/lib/hooks/translate-file.d.ts.bak +59 -0
  109. package/plugins/specweave/lib/hooks/translate-file.js.bak +289 -0
  110. package/plugins/specweave/lib/hooks/translate-file.ts.bak +428 -0
  111. package/plugins/specweave/lib/hooks/translate-living-docs.d.js.bak +0 -0
  112. package/plugins/specweave/lib/hooks/translate-living-docs.d.ts.bak +13 -0
  113. package/plugins/specweave/lib/hooks/translate-living-docs.js.bak +119 -0
  114. package/plugins/specweave/lib/hooks/translate-living-docs.ts.bak +224 -0
  115. package/plugins/specweave/lib/hooks/update-ac-status.js.bak +51 -0
  116. package/plugins/specweave/lib/hooks/update-ac-status.ts.bak +103 -0
  117. package/plugins/specweave/lib/hooks/update-tasks-md.d.js.bak +1 -0
  118. package/plugins/specweave/lib/hooks/update-tasks-md.d.ts.bak +29 -0
  119. package/plugins/specweave/lib/hooks/update-tasks-md.js.bak +296 -0
  120. package/plugins/specweave/lib/hooks/update-tasks-md.ts.bak +489 -0
  121. package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
  122. package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
  123. package/plugins/specweave-ado/lib/ado-multi-project-sync.js +1 -0
  124. package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
  125. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +424 -0
  126. package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
  127. package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
  128. package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
  129. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +540 -0
  130. package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Prepare Reflection Context
3
+ *
4
+ * Prepares context for reflection and saves to temp file
5
+ * Used by post-task-completion hook to prepare for reflection invocation
6
+ *
7
+ * @module prepare-reflection-context
8
+ */
9
+
10
+ import fs from 'fs-extra';
11
+ import path from 'path';
12
+ import { createReflectionContext } from './run-self-reflection';
13
+ import { getModifiedFilesSummary } from './git-diff-analyzer';
14
+
15
+ /**
16
+ * Prepare reflection context and save to temp file
17
+ * This allows the hook to prepare data without actually invoking the agent
18
+ *
19
+ * @param incrementId Increment identifier
20
+ * @param taskId Task identifier
21
+ * @param projectRoot Project root directory (optional)
22
+ * @returns Path to saved context file or null if reflection should be skipped
23
+ */
24
+ export function prepareReflectionContext(
25
+ incrementId: string,
26
+ taskId: string,
27
+ projectRoot?: string
28
+ ): string | null {
29
+ try {
30
+ const context = createReflectionContext(incrementId, taskId, projectRoot);
31
+
32
+ // Check if reflection should run
33
+ if (!context.config.enabled || context.modifiedFiles.length === 0) {
34
+ return null;
35
+ }
36
+
37
+ // Create temp directory for reflection context
38
+ const rootDir = projectRoot || process.cwd();
39
+ const tempDir = path.join(rootDir, '.specweave', 'increments', incrementId, 'logs', 'reflections', '.temp');
40
+ fs.mkdirpSync(tempDir);
41
+
42
+ // Save context to temp file
43
+ const contextFile = path.join(tempDir, 'reflection-context.json');
44
+
45
+ const fileStats = getModifiedFilesSummary(context.modifiedFiles);
46
+
47
+ const contextData = {
48
+ incrementId: context.incrementId,
49
+ taskId: context.taskId,
50
+ modifiedFiles: context.modifiedFiles.map(f => ({
51
+ file: f.file,
52
+ linesAdded: f.linesAdded,
53
+ linesRemoved: f.linesRemoved
54
+ // Exclude diff content to save space
55
+ })),
56
+ fileSummary: {
57
+ count: fileStats.count,
58
+ linesAdded: fileStats.linesAdded,
59
+ linesRemoved: fileStats.linesRemoved
60
+ },
61
+ config: context.config,
62
+ timestamp: new Date().toISOString()
63
+ };
64
+
65
+ fs.writeJsonSync(contextFile, contextData, { spaces: 2 });
66
+
67
+ return contextFile;
68
+ } catch (error: any) {
69
+ console.error(`Failed to prepare reflection context: ${error.message}`);
70
+ return null;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Check if reflection context exists for an increment
76
+ *
77
+ * @param incrementId Increment identifier
78
+ * @param projectRoot Project root directory (optional)
79
+ * @returns True if context file exists
80
+ */
81
+ export function hasReflectionContext(
82
+ incrementId: string,
83
+ projectRoot?: string
84
+ ): boolean {
85
+ const rootDir = projectRoot || process.cwd();
86
+ const contextFile = path.join(
87
+ rootDir,
88
+ '.specweave',
89
+ 'increments',
90
+ incrementId,
91
+ 'logs',
92
+ 'reflections',
93
+ '.temp',
94
+ 'reflection-context.json'
95
+ );
96
+
97
+ return fs.existsSync(contextFile);
98
+ }
99
+
100
+ /**
101
+ * Read reflection context from file
102
+ *
103
+ * @param incrementId Increment identifier
104
+ * @param projectRoot Project root directory (optional)
105
+ * @returns Context data or null if not found
106
+ */
107
+ export function readReflectionContext(
108
+ incrementId: string,
109
+ projectRoot?: string
110
+ ): any | null {
111
+ const rootDir = projectRoot || process.cwd();
112
+ const contextFile = path.join(
113
+ rootDir,
114
+ '.specweave',
115
+ 'increments',
116
+ incrementId,
117
+ 'logs',
118
+ 'reflections',
119
+ '.temp',
120
+ 'reflection-context.json'
121
+ );
122
+
123
+ if (!fs.existsSync(contextFile)) {
124
+ return null;
125
+ }
126
+
127
+ try {
128
+ return fs.readJsonSync(contextFile);
129
+ } catch {
130
+ return null;
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Clear reflection context after reflection completes
136
+ *
137
+ * @param incrementId Increment identifier
138
+ * @param projectRoot Project root directory (optional)
139
+ */
140
+ export function clearReflectionContext(
141
+ incrementId: string,
142
+ projectRoot?: string
143
+ ): void {
144
+ const rootDir = projectRoot || process.cwd();
145
+ const tempDir = path.join(
146
+ rootDir,
147
+ '.specweave',
148
+ 'increments',
149
+ incrementId,
150
+ 'logs',
151
+ 'reflections',
152
+ '.temp'
153
+ );
154
+
155
+ if (fs.existsSync(tempDir)) {
156
+ fs.removeSync(tempDir);
157
+ }
158
+ }
159
+
160
+ // CLI entry point for hook integration
161
+ if (require.main === module) {
162
+ const incrementId = process.argv[2];
163
+ const taskId = process.argv[3];
164
+
165
+ if (!incrementId || !taskId) {
166
+ console.error('Usage: node prepare-reflection-context.js <increment-id> <task-id>');
167
+ process.exit(1);
168
+ }
169
+
170
+ const contextFile = prepareReflectionContext(incrementId, taskId);
171
+
172
+ if (contextFile) {
173
+ console.log(`Reflection context prepared: ${contextFile}`);
174
+ console.log('✨ Reflection ready. Run /specweave:reflect to analyze your work.');
175
+ } else {
176
+ console.log('Reflection skipped (disabled or no changes).');
177
+ }
178
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Reflection Configuration Loader
3
+ *
4
+ * Loads and validates reflection configuration from .specweave/config.json
5
+ * Merges user config with defaults, validates against schema
6
+ *
7
+ * @module reflection-config-loader
8
+ */
9
+ import { ReflectionConfig } from './types/reflection-types';
10
+ /**
11
+ * Find .specweave directory by traversing up from current directory
12
+ * @param startDir Starting directory (defaults to cwd)
13
+ * @returns Path to .specweave directory or null if not found
14
+ */
15
+ export declare function findSpecweaveRoot(startDir?: string): string | null;
16
+ /**
17
+ * Load reflection configuration from .specweave/config.json
18
+ * Falls back to defaults if config file doesn't exist or reflection section is missing
19
+ *
20
+ * @param projectRoot Path to project root (optional, auto-detected if not provided)
21
+ * @returns Merged reflection configuration
22
+ * @throws Error if config file exists but has invalid JSON
23
+ */
24
+ export declare function loadReflectionConfig(projectRoot?: string): ReflectionConfig;
25
+ /**
26
+ * Validate reflection configuration against constraints
27
+ * Checks for logical inconsistencies (e.g., all categories disabled)
28
+ *
29
+ * @param config Reflection configuration to validate
30
+ * @returns Validation result with errors array
31
+ */
32
+ export declare function validateReflectionConfig(config: ReflectionConfig): {
33
+ valid: boolean;
34
+ errors: string[];
35
+ };
36
+ /**
37
+ * Load and validate reflection configuration
38
+ * Throws error if configuration is invalid
39
+ *
40
+ * @param projectRoot Path to project root (optional, auto-detected if not provided)
41
+ * @returns Valid reflection configuration
42
+ * @throws Error if configuration is invalid
43
+ */
44
+ export declare function loadAndValidateReflectionConfig(projectRoot?: string): ReflectionConfig;
45
+ //# sourceMappingURL=reflection-config-loader.d.ts.map
@@ -0,0 +1,92 @@
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+ import { DEFAULT_REFLECTION_CONFIG } from "./types/reflection-types";
4
+ function findSpecweaveRoot(startDir = process.cwd()) {
5
+ let currentDir = startDir;
6
+ const root = path.parse(currentDir).root;
7
+ while (currentDir !== root) {
8
+ const specweavePath = path.join(currentDir, ".specweave");
9
+ if (fs.existsSync(specweavePath)) {
10
+ return currentDir;
11
+ }
12
+ currentDir = path.dirname(currentDir);
13
+ }
14
+ return null;
15
+ }
16
+ function loadReflectionConfig(projectRoot) {
17
+ const rootDir = projectRoot || findSpecweaveRoot();
18
+ if (!rootDir) {
19
+ return { ...DEFAULT_REFLECTION_CONFIG };
20
+ }
21
+ const configPath = path.join(rootDir, ".specweave", "config.json");
22
+ if (!fs.existsSync(configPath)) {
23
+ return { ...DEFAULT_REFLECTION_CONFIG };
24
+ }
25
+ try {
26
+ const configContent = fs.readFileSync(configPath, "utf-8");
27
+ const config = JSON.parse(configContent);
28
+ const userReflectionConfig = config.reflection || {};
29
+ const mergedConfig = {
30
+ enabled: userReflectionConfig.enabled ?? DEFAULT_REFLECTION_CONFIG.enabled,
31
+ mode: userReflectionConfig.mode ?? DEFAULT_REFLECTION_CONFIG.mode,
32
+ depth: userReflectionConfig.depth ?? DEFAULT_REFLECTION_CONFIG.depth,
33
+ model: userReflectionConfig.model ?? DEFAULT_REFLECTION_CONFIG.model,
34
+ categories: {
35
+ security: userReflectionConfig.categories?.security ?? DEFAULT_REFLECTION_CONFIG.categories.security,
36
+ quality: userReflectionConfig.categories?.quality ?? DEFAULT_REFLECTION_CONFIG.categories.quality,
37
+ testing: userReflectionConfig.categories?.testing ?? DEFAULT_REFLECTION_CONFIG.categories.testing,
38
+ performance: userReflectionConfig.categories?.performance ?? DEFAULT_REFLECTION_CONFIG.categories.performance,
39
+ technicalDebt: userReflectionConfig.categories?.technicalDebt ?? DEFAULT_REFLECTION_CONFIG.categories.technicalDebt
40
+ },
41
+ criticalThreshold: userReflectionConfig.criticalThreshold ?? DEFAULT_REFLECTION_CONFIG.criticalThreshold,
42
+ storeReflections: userReflectionConfig.storeReflections ?? DEFAULT_REFLECTION_CONFIG.storeReflections,
43
+ autoCreateFollowUpTasks: userReflectionConfig.autoCreateFollowUpTasks ?? DEFAULT_REFLECTION_CONFIG.autoCreateFollowUpTasks,
44
+ soundNotifications: userReflectionConfig.soundNotifications ?? DEFAULT_REFLECTION_CONFIG.soundNotifications
45
+ };
46
+ return mergedConfig;
47
+ } catch (error) {
48
+ if (error instanceof SyntaxError) {
49
+ throw new Error(`Invalid JSON in config file: ${configPath}. ${error.message}`);
50
+ }
51
+ throw error;
52
+ }
53
+ }
54
+ function validateReflectionConfig(config) {
55
+ const errors = [];
56
+ if (config.enabled && config.mode !== "disabled") {
57
+ const hasEnabledCategory = Object.values(config.categories).some((enabled) => enabled);
58
+ if (!hasEnabledCategory) {
59
+ errors.push("At least one analysis category must be enabled when reflection is active");
60
+ }
61
+ }
62
+ if (!config.enabled && config.mode === "auto") {
63
+ errors.push('Reflection mode cannot be "auto" when reflection is disabled');
64
+ }
65
+ if (config.soundNotifications && !config.enabled) {
66
+ errors.push("Sound notifications require reflection to be enabled");
67
+ }
68
+ if (config.autoCreateFollowUpTasks && !config.storeReflections) {
69
+ errors.push("Auto-create follow-up tasks requires storeReflections to be enabled");
70
+ }
71
+ return {
72
+ valid: errors.length === 0,
73
+ errors
74
+ };
75
+ }
76
+ function loadAndValidateReflectionConfig(projectRoot) {
77
+ const config = loadReflectionConfig(projectRoot);
78
+ const validation = validateReflectionConfig(config);
79
+ if (!validation.valid) {
80
+ throw new Error(
81
+ `Invalid reflection configuration:
82
+ ${validation.errors.map((e) => ` - ${e}`).join("\n")}`
83
+ );
84
+ }
85
+ return config;
86
+ }
87
+ export {
88
+ findSpecweaveRoot,
89
+ loadAndValidateReflectionConfig,
90
+ loadReflectionConfig,
91
+ validateReflectionConfig
92
+ };
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Reflection Configuration Loader
3
+ *
4
+ * Loads and validates reflection configuration from .specweave/config.json
5
+ * Merges user config with defaults, validates against schema
6
+ *
7
+ * @module reflection-config-loader
8
+ */
9
+
10
+ import fs from 'fs-extra';
11
+ import path from 'path';
12
+ import { DEFAULT_REFLECTION_CONFIG, ReflectionConfig } from './types/reflection-types';
13
+
14
+ /**
15
+ * Find .specweave directory by traversing up from current directory
16
+ * @param startDir Starting directory (defaults to cwd)
17
+ * @returns Path to .specweave directory or null if not found
18
+ */
19
+ export function findSpecweaveRoot(startDir: string = process.cwd()): string | null {
20
+ let currentDir = startDir;
21
+ const root = path.parse(currentDir).root;
22
+
23
+ while (currentDir !== root) {
24
+ const specweavePath = path.join(currentDir, '.specweave');
25
+ if (fs.existsSync(specweavePath)) {
26
+ return currentDir;
27
+ }
28
+ currentDir = path.dirname(currentDir);
29
+ }
30
+
31
+ return null;
32
+ }
33
+
34
+ /**
35
+ * Load reflection configuration from .specweave/config.json
36
+ * Falls back to defaults if config file doesn't exist or reflection section is missing
37
+ *
38
+ * @param projectRoot Path to project root (optional, auto-detected if not provided)
39
+ * @returns Merged reflection configuration
40
+ * @throws Error if config file exists but has invalid JSON
41
+ */
42
+ export function loadReflectionConfig(projectRoot?: string): ReflectionConfig {
43
+ // Auto-detect project root if not provided
44
+ const rootDir = projectRoot || findSpecweaveRoot();
45
+
46
+ if (!rootDir) {
47
+ // No .specweave directory found, return defaults
48
+ return { ...DEFAULT_REFLECTION_CONFIG };
49
+ }
50
+
51
+ const configPath = path.join(rootDir, '.specweave', 'config.json');
52
+
53
+ // Config file doesn't exist, return defaults
54
+ if (!fs.existsSync(configPath)) {
55
+ return { ...DEFAULT_REFLECTION_CONFIG };
56
+ }
57
+
58
+ try {
59
+ // Read and parse config file
60
+ const configContent = fs.readFileSync(configPath, 'utf-8');
61
+ const config = JSON.parse(configContent);
62
+
63
+ // Extract reflection section (may be undefined)
64
+ const userReflectionConfig = config.reflection || {};
65
+
66
+ // Deep merge with defaults (user config overrides defaults)
67
+ const mergedConfig: ReflectionConfig = {
68
+ enabled: userReflectionConfig.enabled ?? DEFAULT_REFLECTION_CONFIG.enabled,
69
+ mode: userReflectionConfig.mode ?? DEFAULT_REFLECTION_CONFIG.mode,
70
+ depth: userReflectionConfig.depth ?? DEFAULT_REFLECTION_CONFIG.depth,
71
+ model: userReflectionConfig.model ?? DEFAULT_REFLECTION_CONFIG.model,
72
+ categories: {
73
+ security: userReflectionConfig.categories?.security ?? DEFAULT_REFLECTION_CONFIG.categories.security,
74
+ quality: userReflectionConfig.categories?.quality ?? DEFAULT_REFLECTION_CONFIG.categories.quality,
75
+ testing: userReflectionConfig.categories?.testing ?? DEFAULT_REFLECTION_CONFIG.categories.testing,
76
+ performance: userReflectionConfig.categories?.performance ?? DEFAULT_REFLECTION_CONFIG.categories.performance,
77
+ technicalDebt: userReflectionConfig.categories?.technicalDebt ?? DEFAULT_REFLECTION_CONFIG.categories.technicalDebt,
78
+ },
79
+ criticalThreshold: userReflectionConfig.criticalThreshold ?? DEFAULT_REFLECTION_CONFIG.criticalThreshold,
80
+ storeReflections: userReflectionConfig.storeReflections ?? DEFAULT_REFLECTION_CONFIG.storeReflections,
81
+ autoCreateFollowUpTasks: userReflectionConfig.autoCreateFollowUpTasks ?? DEFAULT_REFLECTION_CONFIG.autoCreateFollowUpTasks,
82
+ soundNotifications: userReflectionConfig.soundNotifications ?? DEFAULT_REFLECTION_CONFIG.soundNotifications,
83
+ };
84
+
85
+ return mergedConfig;
86
+ } catch (error) {
87
+ // Invalid JSON or other error
88
+ if (error instanceof SyntaxError) {
89
+ throw new Error(`Invalid JSON in config file: ${configPath}. ${error.message}`);
90
+ }
91
+ throw error;
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Validate reflection configuration against constraints
97
+ * Checks for logical inconsistencies (e.g., all categories disabled)
98
+ *
99
+ * @param config Reflection configuration to validate
100
+ * @returns Validation result with errors array
101
+ */
102
+ export function validateReflectionConfig(config: ReflectionConfig): {
103
+ valid: boolean;
104
+ errors: string[];
105
+ } {
106
+ const errors: string[] = [];
107
+
108
+ // Check: If reflection enabled, at least one category must be enabled
109
+ if (config.enabled && config.mode !== 'disabled') {
110
+ const hasEnabledCategory = Object.values(config.categories).some(enabled => enabled);
111
+ if (!hasEnabledCategory) {
112
+ errors.push('At least one analysis category must be enabled when reflection is active');
113
+ }
114
+ }
115
+
116
+ // Check: Mode cannot be 'auto' if reflection is disabled
117
+ if (!config.enabled && config.mode === 'auto') {
118
+ errors.push('Reflection mode cannot be "auto" when reflection is disabled');
119
+ }
120
+
121
+ // Check: Sound notifications require reflection to be enabled
122
+ if (config.soundNotifications && !config.enabled) {
123
+ errors.push('Sound notifications require reflection to be enabled');
124
+ }
125
+
126
+ // Check: Auto-create follow-up tasks requires storeReflections
127
+ if (config.autoCreateFollowUpTasks && !config.storeReflections) {
128
+ errors.push('Auto-create follow-up tasks requires storeReflections to be enabled');
129
+ }
130
+
131
+ return {
132
+ valid: errors.length === 0,
133
+ errors
134
+ };
135
+ }
136
+
137
+ /**
138
+ * Load and validate reflection configuration
139
+ * Throws error if configuration is invalid
140
+ *
141
+ * @param projectRoot Path to project root (optional, auto-detected if not provided)
142
+ * @returns Valid reflection configuration
143
+ * @throws Error if configuration is invalid
144
+ */
145
+ export function loadAndValidateReflectionConfig(projectRoot?: string): ReflectionConfig {
146
+ const config = loadReflectionConfig(projectRoot);
147
+ const validation = validateReflectionConfig(config);
148
+
149
+ if (!validation.valid) {
150
+ throw new Error(
151
+ `Invalid reflection configuration:\n${validation.errors.map(e => ` - ${e}`).join('\n')}`
152
+ );
153
+ }
154
+
155
+ return config;
156
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Reflection Parser
3
+ *
4
+ * Parses markdown output from reflective-reviewer agent
5
+ * Extracts structured data (issues, metrics, lessons learned, etc.)
6
+ *
7
+ * @module reflection-parser
8
+ */
9
+ import { ReflectionResult, ReflectionModel } from './types/reflection-types';
10
+ /**
11
+ * Parse complete reflection result from markdown
12
+ * Main parsing function
13
+ *
14
+ * @param markdown Reflection markdown from reflective-reviewer agent
15
+ * @param taskName Task name for result
16
+ * @param model Model used for reflection
17
+ * @param reflectionTime Time taken in seconds
18
+ * @param estimatedCost Estimated cost in USD
19
+ * @returns Complete ReflectionResult object
20
+ */
21
+ export declare function parseReflectionMarkdown(markdown: string, taskName: string, model?: ReflectionModel, reflectionTime?: number, estimatedCost?: number): ReflectionResult;
22
+ /**
23
+ * Validate parsed reflection result
24
+ * Checks for required fields and data quality
25
+ *
26
+ * @param result Parsed reflection result
27
+ * @returns Validation result with errors
28
+ */
29
+ export declare function validateReflectionResult(result: ReflectionResult): {
30
+ valid: boolean;
31
+ errors: string[];
32
+ };
33
+ //# sourceMappingURL=reflection-parser.d.ts.map