@polymorphism-tech/morph-spec 4.2.0 → 4.3.0

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