@polymorphism-tech/morph-spec 4.2.0 → 4.3.1

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 (140) hide show
  1. package/CLAUDE.md +108 -946
  2. package/bin/morph-spec.js +284 -9
  3. package/bin/task-manager.cjs +102 -14
  4. package/bin/validate.js +4 -4
  5. package/docs/{v3.0 → next-generation}/AGENTS.md +1 -1
  6. package/docs/next-generation/CONTEXT-OPTIMIZATION.md +267 -0
  7. package/docs/next-generation/EXECUTION-FLOW.md +274 -0
  8. package/docs/next-generation/META-PROMPTS.md +235 -0
  9. package/docs/next-generation/MIGRATION-GUIDE.md +253 -0
  10. package/docs/next-generation/THREAD-MANAGEMENT.md +240 -0
  11. package/package.json +5 -5
  12. package/src/commands/agents/agents-fuse.js +97 -0
  13. package/src/commands/agents/micro-agent.js +112 -0
  14. package/src/commands/agents/spawn-team.js +69 -4
  15. package/src/commands/agents/squad-template.js +146 -0
  16. package/src/commands/analytics/analytics.js +176 -0
  17. package/src/commands/context/context-prime.js +63 -0
  18. package/src/commands/context/core-four.js +54 -0
  19. package/src/commands/mcp/mcp.js +102 -0
  20. package/src/commands/project/detect-agents.js +32 -2
  21. package/src/commands/project/detect.js +11 -1
  22. package/src/commands/project/doctor.js +573 -356
  23. package/src/commands/project/init.js +9 -2
  24. package/src/commands/project/update.js +13 -3
  25. package/src/commands/state/advance-phase.js +448 -416
  26. package/src/commands/state/state.js +14 -12
  27. package/src/commands/tasks/task.js +1 -1
  28. package/src/commands/templates/template-render.js +80 -1
  29. package/src/commands/threads/thread-template.js +103 -0
  30. package/src/commands/threads/threads.js +261 -0
  31. package/src/commands/trust/trust.js +205 -0
  32. package/src/{orchestrator.js → core/orchestrator.js} +8 -8
  33. package/src/core/state/state-manager.js +37 -17
  34. package/src/core/workflows/workflow-detector.js +114 -3
  35. package/src/lib/agents/micro-agent-factory.js +161 -0
  36. package/src/lib/analytics/analytics-engine.js +345 -0
  37. package/src/lib/checkpoints/checkpoint-hooks.js +298 -258
  38. package/src/lib/context/context-bundler.js +240 -0
  39. package/src/lib/context/context-optimizer.js +212 -0
  40. package/src/lib/context/context-tracker.js +273 -0
  41. package/src/lib/context/core-four-tracker.js +201 -0
  42. package/src/lib/context/mcp-optimizer.js +200 -0
  43. package/src/lib/detectors/index.js +1 -1
  44. package/src/lib/detectors/standards-generator.js +77 -17
  45. package/src/lib/detectors/structure-detector.js +67 -39
  46. package/src/lib/execution/fusion-executor.js +304 -0
  47. package/src/lib/execution/parallel-executor.js +270 -0
  48. package/src/lib/generators/context-generator.js +3 -3
  49. package/src/lib/generators/recap-generator.js +32 -12
  50. package/src/lib/hooks/hook-executor.js +169 -0
  51. package/src/lib/hooks/stop-hook-executor.js +286 -0
  52. package/src/lib/hops/hop-composer.js +221 -0
  53. package/src/lib/threads/thread-coordinator.js +238 -0
  54. package/src/lib/threads/thread-manager.js +317 -0
  55. package/src/lib/tracking/artifact-trail.js +202 -0
  56. package/src/lib/trust/trust-manager.js +269 -0
  57. package/src/lib/validators/design-system/design-system-validator.js +2 -2
  58. package/src/lib/validators/validation-runner.js +14 -30
  59. package/src/utils/hooks-installer.js +69 -0
  60. package/stacks/blazor-azure/.morph/config/agents.json +72 -3
  61. package/stacks/nextjs-supabase/.morph/config/agents.json +3 -3
  62. package/docs/llm-interaction-config.md +0 -735
  63. package/docs/v3.0/EXECUTION-FLOW.md +0 -1304
  64. package/src/commands/utils/migrate-state.js +0 -158
  65. package/src/commands/utils/upgrade.js +0 -346
  66. package/src/lib/validators/architecture-validator.js +0 -60
  67. package/src/lib/validators/content-validator.js +0 -164
  68. package/src/lib/validators/package-validator.js +0 -61
  69. package/src/lib/validators/ui-contrast-validator.js +0 -44
  70. package/stacks/blazor-azure/.claude/commands/morph-apply.md +0 -221
  71. package/stacks/blazor-azure/.claude/commands/morph-archive.md +0 -79
  72. package/stacks/blazor-azure/.claude/commands/morph-deploy.md +0 -529
  73. package/stacks/blazor-azure/.claude/commands/morph-infra.md +0 -209
  74. package/stacks/blazor-azure/.claude/commands/morph-preflight.md +0 -227
  75. package/stacks/blazor-azure/.claude/commands/morph-proposal.md +0 -122
  76. package/stacks/blazor-azure/.claude/commands/morph-status.md +0 -86
  77. package/stacks/blazor-azure/.claude/commands/morph-troubleshoot.md +0 -122
  78. package/stacks/blazor-azure/.claude/skills/level-0-meta/README.md +0 -7
  79. package/stacks/blazor-azure/.claude/skills/level-0-meta/code-review.md +0 -226
  80. package/stacks/blazor-azure/.claude/skills/level-0-meta/morph-checklist.md +0 -117
  81. package/stacks/blazor-azure/.claude/skills/level-0-meta/simulation-checklist.md +0 -77
  82. package/stacks/blazor-azure/.claude/skills/level-1-workflows/README.md +0 -7
  83. package/stacks/blazor-azure/.claude/skills/level-1-workflows/morph-replicate.md +0 -213
  84. package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-clarify.md +0 -131
  85. package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-design.md +0 -213
  86. package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-setup.md +0 -106
  87. package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-tasks.md +0 -164
  88. package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-uiux.md +0 -169
  89. package/stacks/blazor-azure/.claude/skills/level-2-domains/README.md +0 -14
  90. package/stacks/blazor-azure/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +0 -192
  91. package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/po-pm-advisor.md +0 -197
  92. package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/prompt-engineer.md +0 -189
  93. package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/seo-growth-hacker.md +0 -320
  94. package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/standards-architect.md +0 -156
  95. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/api-designer.md +0 -59
  96. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/dotnet-senior.md +0 -77
  97. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ef-modeler.md +0 -58
  98. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/hangfire-orchestrator.md +0 -126
  99. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ms-agent-expert.md +0 -45
  100. package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/blazor-builder.md +0 -210
  101. package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/nextjs-expert.md +0 -154
  102. package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/ui-ux-designer.md +0 -191
  103. package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/azure-architect.md +0 -142
  104. package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/azure-deploy-specialist.md +0 -699
  105. package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/bicep-architect.md +0 -126
  106. package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/container-specialist.md +0 -131
  107. package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/devops-engineer.md +0 -119
  108. package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/asaas-financial.md +0 -130
  109. package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/azure-identity.md +0 -142
  110. package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/clerk-auth.md +0 -108
  111. package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/hangfire-orchestrator.md +0 -64
  112. package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/resend-email.md +0 -119
  113. package/stacks/blazor-azure/.claude/skills/level-2-domains/quality/code-analyzer.md +0 -235
  114. package/stacks/blazor-azure/.claude/skills/level-2-domains/quality/testing-specialist.md +0 -126
  115. package/stacks/blazor-azure/.claude/skills/level-3-technologies/README.md +0 -7
  116. package/stacks/blazor-azure/.claude/skills/level-4-patterns/README.md +0 -7
  117. package/stacks/blazor-azure/.morph/archive/.gitkeep +0 -25
  118. package/stacks/blazor-azure/.morph/features/.gitkeep +0 -25
  119. package/stacks/blazor-azure/.morph/schemas/agent.schema.json +0 -296
  120. package/stacks/blazor-azure/.morph/schemas/tasks.schema.json +0 -220
  121. package/stacks/blazor-azure/.morph/specs/.gitkeep +0 -20
  122. package/stacks/blazor-azure/.morph/test-infra/example.bicep +0 -59
  123. package/stacks/nextjs-supabase/.claude/commands/morph-apply.md +0 -221
  124. package/stacks/nextjs-supabase/.claude/commands/morph-archive.md +0 -79
  125. package/stacks/nextjs-supabase/.claude/commands/morph-deploy.md +0 -529
  126. package/stacks/nextjs-supabase/.claude/commands/morph-infra.md +0 -209
  127. package/stacks/nextjs-supabase/.claude/commands/morph-preflight.md +0 -227
  128. package/stacks/nextjs-supabase/.claude/commands/morph-proposal.md +0 -122
  129. package/stacks/nextjs-supabase/.claude/commands/morph-status.md +0 -86
  130. package/stacks/nextjs-supabase/.claude/commands/morph-troubleshoot.md +0 -122
  131. package/stacks/nextjs-supabase/.claude/settings.local.json +0 -6
  132. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/backend/dotnet-supabase.md +0 -244
  133. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/frontend/nextjs-supabase.md +0 -335
  134. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/infrastructure/easypanel-deployer.md +0 -189
  135. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/integrations/supabase-expert.md +0 -50
  136. /package/docs/{v3.0 → next-generation}/ANALYSIS.md +0 -0
  137. /package/docs/{v3.0 → next-generation}/ARCHITECTURE.md +0 -0
  138. /package/docs/{v3.0 → next-generation}/FEATURES.md +0 -0
  139. /package/docs/{v3.0 → next-generation}/README.md +0 -0
  140. /package/docs/{v3.0 → next-generation}/ROADMAP.md +0 -0
@@ -1,258 +1,298 @@
1
- import { readFileSync, existsSync } from 'fs';
2
- import { join } from 'path';
3
- import { execSync } from 'child_process';
4
-
5
- /**
6
- * Checkpoint Hooks - Automated validation orchestration
7
- *
8
- * Runs validators, tests, and linters at checkpoint milestones (every N tasks).
9
- * Blocks progress if critical validations fail.
10
- */
11
-
12
- /**
13
- * Load LLM interaction configuration
14
- * @returns {Object} Configuration object
15
- */
16
- function loadLLMInteractionConfig() {
17
- const configPath = join(process.cwd(), '.morph/config/llm-interaction.json');
18
-
19
- if (!existsSync(configPath)) {
20
- // Return defaults if config doesn't exist
21
- return {
22
- checkpoints: {
23
- frequency: 3,
24
- autoValidate: true,
25
- validators: {
26
- enabled: ['architecture', 'packages', 'design-system', 'security'],
27
- optional: []
28
- },
29
- hooks: {
30
- runTests: false,
31
- runLinters: true,
32
- buildCheck: false
33
- },
34
- onFailure: {
35
- blockProgress: true,
36
- maxRetries: 3,
37
- escalateAfter: 3
38
- }
39
- }
40
- };
41
- }
42
-
43
- return JSON.parse(readFileSync(configPath, 'utf8'));
44
- }
45
-
46
- /**
47
- * Run a single validator
48
- * @param {string} validatorName - Validator to run (architecture, packages, etc.)
49
- * @param {string} featureName - Feature being validated
50
- * @returns {Promise<Object>} Validation result
51
- */
52
- async function runValidator(validatorName, featureName) {
53
- try {
54
- // Use existing validate command
55
- const result = execSync(
56
- `node bin/validate.js ${validatorName} --feature=${featureName} --json`,
57
- { encoding: 'utf8', stdio: 'pipe' }
58
- );
59
-
60
- const parsed = JSON.parse(result);
61
- return {
62
- validator: validatorName,
63
- passed: parsed.errors === 0,
64
- errors: parsed.errors || 0,
65
- warnings: parsed.warnings || 0,
66
- details: parsed.issues || []
67
- };
68
- } catch (error) {
69
- return {
70
- validator: validatorName,
71
- passed: false,
72
- errors: 1,
73
- warnings: 0,
74
- details: [{ message: error.message, severity: 'error' }]
75
- };
76
- }
77
- }
78
-
79
- /**
80
- * Run tests if configured
81
- * @param {string} featureName - Feature being tested
82
- * @returns {Promise<Object>} Test result
83
- */
84
- async function runTests(featureName) {
85
- try {
86
- execSync('npm test --passWithNoTests', { encoding: 'utf8', stdio: 'pipe' });
87
- return {
88
- validator: 'tests',
89
- passed: true,
90
- errors: 0,
91
- warnings: 0,
92
- details: []
93
- };
94
- } catch (error) {
95
- return {
96
- validator: 'tests',
97
- passed: false,
98
- errors: 1,
99
- warnings: 0,
100
- details: [{ message: 'Test suite failed', severity: 'error' }]
101
- };
102
- }
103
- }
104
-
105
- /**
106
- * Run linters if configured
107
- * @param {string} featureName - Feature being linted
108
- * @returns {Promise<Object>} Linter result
109
- */
110
- async function runLinters(featureName) {
111
- try {
112
- // Check if eslint exists
113
- if (existsSync(join(process.cwd(), 'node_modules/.bin/eslint'))) {
114
- execSync('npm run lint --if-present', { encoding: 'utf8', stdio: 'pipe' });
115
- }
116
-
117
- return {
118
- validator: 'linters',
119
- passed: true,
120
- errors: 0,
121
- warnings: 0,
122
- details: []
123
- };
124
- } catch (error) {
125
- return {
126
- validator: 'linters',
127
- passed: false,
128
- errors: 0,
129
- warnings: 1,
130
- details: [{ message: 'Linting warnings detected', severity: 'warning' }]
131
- };
132
- }
133
- }
134
-
135
- /**
136
- * Run checkpoint hooks - orchestrates all validation
137
- * @param {string} featureName - Feature name
138
- * @param {number} checkpointNum - Checkpoint number (1, 2, 3, etc.)
139
- * @returns {Promise<Object>} Checkpoint result
140
- */
141
- export async function runCheckpointHooks(featureName, checkpointNum) {
142
- const config = loadLLMInteractionConfig();
143
- const checkpointConfig = config.checkpoints;
144
-
145
- if (!checkpointConfig.autoValidate) {
146
- return {
147
- passed: true,
148
- skipped: true,
149
- message: 'Auto-validation disabled in config'
150
- };
151
- }
152
-
153
- console.log(`\n🔍 Running CHECKPOINT ${checkpointNum} for feature: ${featureName}`);
154
- console.log('━'.repeat(60));
155
-
156
- const results = [];
157
-
158
- // 1. Run enabled validators
159
- console.log('\n📋 Running validators...');
160
- for (const validatorName of checkpointConfig.validators.enabled) {
161
- process.stdout.write(` • ${validatorName}... `);
162
- const result = await runValidator(validatorName, featureName);
163
- results.push(result);
164
-
165
- if (result.passed) {
166
- console.log('✅ PASSED');
167
- } else {
168
- console.log(`❌ FAILED (${result.errors} errors, ${result.warnings} warnings)`);
169
- }
170
- }
171
-
172
- // 2. Run tests (if configured)
173
- if (checkpointConfig.hooks.runTests) {
174
- console.log('\n🧪 Running tests...');
175
- process.stdout.write(' • test suite... ');
176
- const testResult = await runTests(featureName);
177
- results.push(testResult);
178
-
179
- if (testResult.passed) {
180
- console.log('✅ PASSED');
181
- } else {
182
- console.log('❌ FAILED');
183
- }
184
- }
185
-
186
- // 3. Run linters (if configured)
187
- if (checkpointConfig.hooks.runLinters) {
188
- console.log('\n🎨 Running linters...');
189
- process.stdout.write(' • code style... ');
190
- const lintResult = await runLinters(featureName);
191
- results.push(lintResult);
192
-
193
- if (lintResult.passed) {
194
- console.log('✅ PASSED');
195
- } else {
196
- console.log('⚠️ WARNINGS');
197
- }
198
- }
199
-
200
- // Calculate overall pass/fail
201
- const errorCount = results.reduce((sum, r) => sum + r.errors, 0);
202
- const warningCount = results.reduce((sum, r) => sum + r.warnings, 0);
203
- const passed = errorCount === 0;
204
-
205
- console.log('\n' + '━'.repeat(60));
206
- console.log(`\n📊 Checkpoint ${checkpointNum} Summary:`);
207
- console.log(` Errors: ${errorCount}`);
208
- console.log(` Warnings: ${warningCount}`);
209
- console.log(` Status: ${passed ? '✅ PASSED' : '❌ FAILED'}`);
210
-
211
- if (!passed) {
212
- console.log('\n⚠️ Checkpoint failed! Fix violations before proceeding.');
213
-
214
- // Show details of failures
215
- results.filter(r => r.errors > 0).forEach(r => {
216
- console.log(`\n ${r.validator} errors:`);
217
- r.details.forEach(d => {
218
- if (d.severity === 'error') {
219
- console.log(` - ${d.message}`);
220
- }
221
- });
222
- });
223
- }
224
-
225
- console.log('\n' + '━'.repeat(60) + '\n');
226
-
227
- return {
228
- passed,
229
- checkpointNum,
230
- timestamp: new Date().toISOString(),
231
- results,
232
- summary: {
233
- errors: errorCount,
234
- warnings: warningCount,
235
- validatorsRun: results.length
236
- }
237
- };
238
- }
239
-
240
- /**
241
- * Check if checkpoint should run based on task count
242
- * @param {number} tasksCompleted - Number of tasks completed
243
- * @param {number} frequency - Checkpoint frequency (default: 3)
244
- * @returns {boolean} True if checkpoint should run
245
- */
246
- export function shouldRunCheckpoint(tasksCompleted, frequency = 3) {
247
- return tasksCompleted > 0 && tasksCompleted % frequency === 0;
248
- }
249
-
250
- /**
251
- * Get checkpoint number from task count
252
- * @param {number} tasksCompleted - Number of tasks completed
253
- * @param {number} frequency - Checkpoint frequency (default: 3)
254
- * @returns {number} Checkpoint number
255
- */
256
- export function getCheckpointNumber(tasksCompleted, frequency = 3) {
257
- return Math.floor(tasksCompleted / frequency);
258
- }
1
+ import { readFileSync, existsSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { execSync } from 'child_process';
4
+ import chalk from 'chalk';
5
+ import { executeStopHooks, isMaxRetriesExceeded, incrementRetryCount } from '../hooks/stop-hook-executor.js';
6
+ import { recordEvent } from '../analytics/analytics-engine.js';
7
+ import { getFeature } from '../../core/state/state-manager.js';
8
+
9
+ /**
10
+ * Checkpoint Hooks - Automated validation orchestration
11
+ *
12
+ * Runs validators, tests, and linters at checkpoint milestones (every N tasks).
13
+ * Blocks progress if critical validations fail.
14
+ */
15
+
16
+ /**
17
+ * Load LLM interaction configuration
18
+ * @returns {Object} Configuration object
19
+ */
20
+ function loadLLMInteractionConfig() {
21
+ const configPath = join(process.cwd(), '.morph/config/llm-interaction.json');
22
+
23
+ if (!existsSync(configPath)) {
24
+ // Return defaults if config doesn't exist
25
+ return {
26
+ checkpoints: {
27
+ frequency: 3,
28
+ autoValidate: true,
29
+ validators: {
30
+ enabled: ['architecture', 'packages', 'design-system', 'security'],
31
+ optional: []
32
+ },
33
+ hooks: {
34
+ runTests: false,
35
+ runLinters: true,
36
+ buildCheck: false
37
+ },
38
+ onFailure: {
39
+ blockProgress: true,
40
+ maxRetries: 3,
41
+ escalateAfter: 3
42
+ }
43
+ }
44
+ };
45
+ }
46
+
47
+ return JSON.parse(readFileSync(configPath, 'utf8'));
48
+ }
49
+
50
+ /**
51
+ * Run a single validator
52
+ * @param {string} validatorName - Validator to run (architecture, packages, etc.)
53
+ * @param {string} featureName - Feature being validated
54
+ * @returns {Promise<Object>} Validation result
55
+ */
56
+ async function runValidator(validatorName, featureName) {
57
+ try {
58
+ // Use existing validate command
59
+ const result = execSync(
60
+ `node bin/validate.js ${validatorName} --feature=${featureName} --json`,
61
+ { encoding: 'utf8', stdio: 'pipe' }
62
+ );
63
+
64
+ const parsed = JSON.parse(result);
65
+ return {
66
+ validator: validatorName,
67
+ passed: parsed.errors === 0,
68
+ errors: parsed.errors || 0,
69
+ warnings: parsed.warnings || 0,
70
+ details: parsed.issues || []
71
+ };
72
+ } catch (error) {
73
+ return {
74
+ validator: validatorName,
75
+ passed: false,
76
+ errors: 1,
77
+ warnings: 0,
78
+ details: [{ message: error.message, severity: 'error' }]
79
+ };
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Run tests if configured
85
+ * @param {string} featureName - Feature being tested
86
+ * @returns {Promise<Object>} Test result
87
+ */
88
+ async function runTests(featureName) {
89
+ try {
90
+ execSync('npm test --passWithNoTests', { encoding: 'utf8', stdio: 'pipe' });
91
+ return {
92
+ validator: 'tests',
93
+ passed: true,
94
+ errors: 0,
95
+ warnings: 0,
96
+ details: []
97
+ };
98
+ } catch (error) {
99
+ return {
100
+ validator: 'tests',
101
+ passed: false,
102
+ errors: 1,
103
+ warnings: 0,
104
+ details: [{ message: 'Test suite failed', severity: 'error' }]
105
+ };
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Run linters if configured
111
+ * @param {string} featureName - Feature being linted
112
+ * @returns {Promise<Object>} Linter result
113
+ */
114
+ async function runLinters(featureName) {
115
+ try {
116
+ // Check if eslint exists
117
+ if (existsSync(join(process.cwd(), 'node_modules/.bin/eslint'))) {
118
+ execSync('npm run lint --if-present', { encoding: 'utf8', stdio: 'pipe' });
119
+ }
120
+
121
+ return {
122
+ validator: 'linters',
123
+ passed: true,
124
+ errors: 0,
125
+ warnings: 0,
126
+ details: []
127
+ };
128
+ } catch (error) {
129
+ return {
130
+ validator: 'linters',
131
+ passed: false,
132
+ errors: 0,
133
+ warnings: 1,
134
+ details: [{ message: 'Linting warnings detected', severity: 'warning' }]
135
+ };
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Run checkpoint hooks - orchestrates all validation
141
+ * @param {string} featureName - Feature name
142
+ * @param {number} checkpointNum - Checkpoint number (1, 2, 3, etc.)
143
+ * @returns {Promise<Object>} Checkpoint result
144
+ */
145
+ export async function runCheckpointHooks(featureName, checkpointNum) {
146
+ const config = loadLLMInteractionConfig();
147
+ const checkpointConfig = config.checkpoints;
148
+
149
+ if (!checkpointConfig.autoValidate) {
150
+ return {
151
+ passed: true,
152
+ skipped: true,
153
+ message: 'Auto-validation disabled in config'
154
+ };
155
+ }
156
+
157
+ console.log(`\n🔍 Running CHECKPOINT ${checkpointNum} for feature: ${featureName}`);
158
+ console.log('━'.repeat(60));
159
+
160
+ const results = [];
161
+
162
+ // 1. Run enabled validators
163
+ console.log('\n📋 Running validators...');
164
+ for (const validatorName of checkpointConfig.validators.enabled) {
165
+ process.stdout.write(` • ${validatorName}... `);
166
+ const result = await runValidator(validatorName, featureName);
167
+ results.push(result);
168
+
169
+ if (result.passed) {
170
+ console.log('✅ PASSED');
171
+ } else {
172
+ console.log(`❌ FAILED (${result.errors} errors, ${result.warnings} warnings)`);
173
+ }
174
+ }
175
+
176
+ // 2. Run tests (if configured)
177
+ if (checkpointConfig.hooks.runTests) {
178
+ console.log('\n🧪 Running tests...');
179
+ process.stdout.write(' • test suite... ');
180
+ const testResult = await runTests(featureName);
181
+ results.push(testResult);
182
+
183
+ if (testResult.passed) {
184
+ console.log('✅ PASSED');
185
+ } else {
186
+ console.log('❌ FAILED');
187
+ }
188
+ }
189
+
190
+ // 3. Run linters (if configured)
191
+ if (checkpointConfig.hooks.runLinters) {
192
+ console.log('\n🎨 Running linters...');
193
+ process.stdout.write(' • code style... ');
194
+ const lintResult = await runLinters(featureName);
195
+ results.push(lintResult);
196
+
197
+ if (lintResult.passed) {
198
+ console.log('✅ PASSED');
199
+ } else {
200
+ console.log('⚠️ WARNINGS');
201
+ }
202
+ }
203
+
204
+ // Calculate overall pass/fail
205
+ const errorCount = results.reduce((sum, r) => sum + r.errors, 0);
206
+ const warningCount = results.reduce((sum, r) => sum + r.warnings, 0);
207
+ const passed = errorCount === 0;
208
+
209
+ console.log('\n' + ''.repeat(60));
210
+ console.log(`\n📊 Checkpoint ${checkpointNum} Summary:`);
211
+ console.log(` Errors: ${errorCount}`);
212
+ console.log(` Warnings: ${warningCount}`);
213
+ console.log(` Status: ${passed ? '✅ PASSED' : '❌ FAILED'}`);
214
+
215
+ if (!passed) {
216
+ console.log('\n⚠️ Checkpoint failed! Fix violations before proceeding.');
217
+
218
+ // Show details of failures
219
+ results.filter(r => r.errors > 0).forEach(r => {
220
+ console.log(`\n❌ ${r.validator} errors:`);
221
+ r.details.forEach(d => {
222
+ if (d.severity === 'error') {
223
+ console.log(` - ${d.message}`);
224
+ }
225
+ });
226
+ });
227
+ }
228
+
229
+ console.log('\n' + '━'.repeat(60) + '\n');
230
+
231
+ // Run stop hooks for L-Thread support
232
+ let stopHookResult = null;
233
+ if (featureName) {
234
+ try {
235
+ // Use feature name as pseudo thread ID for stop hook feedback
236
+ const pseudoThreadId = `checkpoint-${featureName}-${checkpointNum}`;
237
+ stopHookResult = await executeStopHooks(pseudoThreadId, 'on-stop', { feature: featureName });
238
+
239
+ if (!stopHookResult.passed) {
240
+ // Check retry count
241
+ let retryCount = null;
242
+ if (isMaxRetriesExceeded(pseudoThreadId)) {
243
+ console.log(chalk.red('\n❌ Stop hooks failed 5+ times. Escalating to user.'));
244
+ } else {
245
+ retryCount = incrementRetryCount(pseudoThreadId);
246
+ console.log(chalk.yellow(`\n⚠ Stop hooks failed (attempt ${retryCount}/5). Feedback saved.`));
247
+ if (stopHookResult.feedback?.suggestions?.length > 0) {
248
+ stopHookResult.feedback.suggestions.forEach(s => console.log(` → ${s}`));
249
+ }
250
+ }
251
+
252
+ // Record to analytics
253
+ recordEvent({
254
+ type: 'stop_hook_failed_at_checkpoint',
255
+ feature: featureName,
256
+ data: { checkpointNum, retryCount }
257
+ });
258
+ }
259
+ } catch {
260
+ // Stop hooks are non-critical — don't block checkpoint if they error
261
+ }
262
+ }
263
+
264
+ const phase = featureName ? (getFeature(featureName)?.phase || null) : null;
265
+
266
+ return {
267
+ passed,
268
+ checkpointNum,
269
+ timestamp: new Date().toISOString(),
270
+ phase,
271
+ results,
272
+ summary: {
273
+ errors: errorCount,
274
+ warnings: warningCount,
275
+ validatorsRun: results.length
276
+ }
277
+ };
278
+ }
279
+
280
+ /**
281
+ * Check if checkpoint should run based on task count
282
+ * @param {number} tasksCompleted - Number of tasks completed
283
+ * @param {number} frequency - Checkpoint frequency (default: 3)
284
+ * @returns {boolean} True if checkpoint should run
285
+ */
286
+ export function shouldRunCheckpoint(tasksCompleted, frequency = 3) {
287
+ return tasksCompleted > 0 && tasksCompleted % frequency === 0;
288
+ }
289
+
290
+ /**
291
+ * Get checkpoint number from task count
292
+ * @param {number} tasksCompleted - Number of tasks completed
293
+ * @param {number} frequency - Checkpoint frequency (default: 3)
294
+ * @returns {number} Checkpoint number
295
+ */
296
+ export function getCheckpointNumber(tasksCompleted, frequency = 3) {
297
+ return Math.floor(tasksCompleted / frequency);
298
+ }