@iservu-inc/adf-cli 0.4.34 → 0.4.35
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/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,94 @@ All notable changes to `@iservu-inc/adf-cli` will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.4.35] - 2025-10-04
|
|
9
|
+
|
|
10
|
+
### 🔧 MAJOR FIX: Windsurf Configuration - Activation Modes & Content Generation
|
|
11
|
+
|
|
12
|
+
**Fixed: Empty/Useless Windsurf Files**
|
|
13
|
+
- **Problem:** Generated Windsurf files had wrong activation modes and empty content
|
|
14
|
+
- **Issues:**
|
|
15
|
+
1. Rules had `Manual` activation (useless) instead of `Always On`
|
|
16
|
+
2. Workflows had no activation mode frontmatter
|
|
17
|
+
3. Content showed "Not provided" instead of actual answers
|
|
18
|
+
4. Not reading session data to extract meaningful information
|
|
19
|
+
|
|
20
|
+
**Solution:**
|
|
21
|
+
1. **Added Proper Frontmatter with Activation Modes:**
|
|
22
|
+
- Rules: `trigger: always_on` (default for most rules)
|
|
23
|
+
- Workflows: `trigger: manual` with descriptions
|
|
24
|
+
- Follows Windsurf best practices
|
|
25
|
+
|
|
26
|
+
2. **Reads Actual Session Answers:**
|
|
27
|
+
- New `loadSessionAnswers()` loads `_progress.json`
|
|
28
|
+
- Extracts real answers from interview session
|
|
29
|
+
- Falls back gracefully if data unavailable
|
|
30
|
+
|
|
31
|
+
3. **Intelligent Content Parsing:**
|
|
32
|
+
- New `parseImplementationBlueprint()` extracts structured sections
|
|
33
|
+
- New `extractSubsection()` finds content by keywords
|
|
34
|
+
- New `extractTechStackFromAnswers()` finds tech mentions
|
|
35
|
+
- New `extractWhatBuildingFromAnswers()` finds project goals
|
|
36
|
+
|
|
37
|
+
**Before v0.4.35 (Broken):**
|
|
38
|
+
```markdown
|
|
39
|
+
# Architecture - adf-test-project
|
|
40
|
+
|
|
41
|
+
## Implementation Blueprint
|
|
42
|
+
Not provided
|
|
43
|
+
|
|
44
|
+
## Data Model
|
|
45
|
+
Not provided
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**After v0.4.35 (Fixed):**
|
|
49
|
+
```markdown
|
|
50
|
+
---
|
|
51
|
+
trigger: always_on
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
# Architecture - adf-test-project
|
|
55
|
+
|
|
56
|
+
## Implementation Blueprint
|
|
57
|
+
|
|
58
|
+
### Implementation Steps
|
|
59
|
+
**Project Goal:**
|
|
60
|
+
A performance website with nextjs frontend, postgres database...
|
|
61
|
+
|
|
62
|
+
### Technical Approach
|
|
63
|
+
**Tech Stack:**
|
|
64
|
+
Next.js for frontend and backend, PostgreSQL for database...
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Code Changes:**
|
|
68
|
+
- windsurf-generator.js:217-289 - Added frontmatter to project-context rule
|
|
69
|
+
- windsurf-generator.js:296-359 - Added frontmatter & parsing to architecture rule
|
|
70
|
+
- windsurf-generator.js:381-437 - Added frontmatter to coding-standards rule
|
|
71
|
+
- windsurf-generator.js:465-545 - Added frontmatter & descriptions to workflows
|
|
72
|
+
- windsurf-generator.js:633-754 - NEW helper methods for answer parsing
|
|
73
|
+
|
|
74
|
+
**New Helper Methods:**
|
|
75
|
+
- `loadSessionAnswers()` - Reads _progress.json
|
|
76
|
+
- `parseImplementationBlueprint()` - Parses blueprint into sections
|
|
77
|
+
- `extractSubsection()` - Finds content by keyword matching
|
|
78
|
+
- `extractTechStackFromAnswers()` - Detects tech stack in answers
|
|
79
|
+
- `extractWhatBuildingFromAnswers()` - Finds project goals
|
|
80
|
+
|
|
81
|
+
**Activation Modes Guide:**
|
|
82
|
+
- **Always On:** Default for rules - always active
|
|
83
|
+
- **Glob:** For file/pattern matching (not used yet)
|
|
84
|
+
- **Manual:** For workflows - user must activate
|
|
85
|
+
- **Model Decide:** AI chooses when to activate (requires description)
|
|
86
|
+
|
|
87
|
+
**Impact:**
|
|
88
|
+
- ✅ Windsurf rules now work properly with `Always On` activation
|
|
89
|
+
- ✅ Files contain actual project information, not placeholders
|
|
90
|
+
- ✅ Workflows have proper frontmatter with descriptions
|
|
91
|
+
- ✅ Better content extraction from session answers
|
|
92
|
+
- ✅ Fallback to PRP/specification if answers unavailable
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
8
96
|
## [0.4.34] - 2025-10-04
|
|
9
97
|
|
|
10
98
|
### ✨ Feature: Multi-Tool Deployment Selection
|
|
@@ -214,7 +214,11 @@ ${this.extractSection(this.outputs.architecture || '', 'System Overview') || 'Se
|
|
|
214
214
|
let content;
|
|
215
215
|
if (this.framework === 'rapid') {
|
|
216
216
|
const sections = this.outputs.sections || {};
|
|
217
|
-
content =
|
|
217
|
+
content = `---
|
|
218
|
+
trigger: always_on
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
# Project Context - ${projectName}
|
|
218
222
|
|
|
219
223
|
## Goal
|
|
220
224
|
|
|
@@ -235,7 +239,11 @@ All requirements are documented in: \`.adf/sessions/${this.getSessionId()}/outpu
|
|
|
235
239
|
Read this file before implementing any features.
|
|
236
240
|
`;
|
|
237
241
|
} else if (this.framework === 'balanced') {
|
|
238
|
-
content =
|
|
242
|
+
content = `---
|
|
243
|
+
trigger: always_on
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
# Project Context - ${projectName}
|
|
239
247
|
|
|
240
248
|
## Overview
|
|
241
249
|
|
|
@@ -257,7 +265,11 @@ Review these files before implementing:
|
|
|
257
265
|
- Technical Plan: \`.adf/sessions/${this.getSessionId()}/outputs/plan.md\`
|
|
258
266
|
`;
|
|
259
267
|
} else {
|
|
260
|
-
content =
|
|
268
|
+
content = `---
|
|
269
|
+
trigger: always_on
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
# Project Context - ${projectName}
|
|
261
273
|
|
|
262
274
|
## Product Overview
|
|
263
275
|
|
|
@@ -282,21 +294,52 @@ Review these files before implementing:
|
|
|
282
294
|
async generateArchitectureRule() {
|
|
283
295
|
const projectName = this.getProjectName();
|
|
284
296
|
|
|
297
|
+
// Load actual session answers for better content
|
|
298
|
+
const answers = await this.loadSessionAnswers();
|
|
299
|
+
|
|
285
300
|
let content;
|
|
286
301
|
if (this.framework === 'rapid') {
|
|
287
302
|
const sections = this.outputs.sections || {};
|
|
288
|
-
|
|
303
|
+
const blueprint = sections['4._implementation_blueprint'] || sections['implementation_blueprint'];
|
|
304
|
+
|
|
305
|
+
// Parse blueprint into structured sections
|
|
306
|
+
const parsed = this.parseImplementationBlueprint(blueprint || '', answers);
|
|
307
|
+
|
|
308
|
+
content = `---
|
|
309
|
+
trigger: always_on
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
# Architecture - ${projectName}
|
|
289
313
|
|
|
290
314
|
## Implementation Blueprint
|
|
291
315
|
|
|
292
|
-
|
|
316
|
+
### Implementation Steps
|
|
317
|
+
${parsed.steps || 'Not provided'}
|
|
318
|
+
|
|
319
|
+
### Data Model
|
|
320
|
+
${parsed.dataModel || 'Not provided'}
|
|
321
|
+
|
|
322
|
+
### API Design
|
|
323
|
+
${parsed.apiDesign || 'Not provided'}
|
|
324
|
+
|
|
325
|
+
### Edge Cases & Error Handling
|
|
326
|
+
${parsed.errorHandling || 'Not provided'}
|
|
327
|
+
|
|
328
|
+
### Technical Approach
|
|
329
|
+
${parsed.technicalApproach || 'Not provided'}
|
|
330
|
+
|
|
331
|
+
---
|
|
293
332
|
|
|
294
333
|
## Reference
|
|
295
334
|
|
|
296
335
|
Full implementation details: \`.adf/sessions/${this.getSessionId()}/outputs/prp.md\`
|
|
297
336
|
`;
|
|
298
337
|
} else if (this.framework === 'balanced') {
|
|
299
|
-
content =
|
|
338
|
+
content = `---
|
|
339
|
+
trigger: always_on
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
# Architecture - ${projectName}
|
|
300
343
|
|
|
301
344
|
${this.extractSection(this.outputs.specification || '', 'Architecture') || 'See specification'}
|
|
302
345
|
|
|
@@ -309,7 +352,11 @@ ${this.extractSection(this.outputs.plan || '', 'Architecture') || 'See technical
|
|
|
309
352
|
Full architecture: \`.adf/sessions/${this.getSessionId()}/outputs/specification.md\`
|
|
310
353
|
`;
|
|
311
354
|
} else {
|
|
312
|
-
content =
|
|
355
|
+
content = `---
|
|
356
|
+
trigger: always_on
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
# Architecture - ${projectName}
|
|
313
360
|
|
|
314
361
|
${this.extractSection(this.outputs.architecture || '', 'System Overview') || 'See architecture.md'}
|
|
315
362
|
|
|
@@ -331,7 +378,11 @@ Full architecture: \`.adf/sessions/${this.getSessionId()}/outputs/architecture.m
|
|
|
331
378
|
|
|
332
379
|
let content;
|
|
333
380
|
if (this.framework === 'rapid') {
|
|
334
|
-
content =
|
|
381
|
+
content = `---
|
|
382
|
+
trigger: always_on
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
# Coding Standards - ${projectName}
|
|
335
386
|
|
|
336
387
|
## General Guidelines
|
|
337
388
|
|
|
@@ -346,7 +397,11 @@ Full architecture: \`.adf/sessions/${this.getSessionId()}/outputs/architecture.m
|
|
|
346
397
|
See implementation blueprint in: \`.adf/sessions/${this.getSessionId()}/outputs/prp.md\`
|
|
347
398
|
`;
|
|
348
399
|
} else if (this.framework === 'balanced') {
|
|
349
|
-
content =
|
|
400
|
+
content = `---
|
|
401
|
+
trigger: always_on
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
# Coding Standards - ${projectName}
|
|
350
405
|
|
|
351
406
|
${this.extractSection(this.outputs.plan || '', 'Code Style') || this.extractSection(this.outputs.plan || '', 'Coding Standards') || ''}
|
|
352
407
|
|
|
@@ -359,7 +414,11 @@ ${this.extractSection(this.outputs.constitution || '', 'Core Principles') || 'Fo
|
|
|
359
414
|
Full standards: \`.adf/sessions/${this.getSessionId()}/outputs/plan.md\`
|
|
360
415
|
`;
|
|
361
416
|
} else {
|
|
362
|
-
content =
|
|
417
|
+
content = `---
|
|
418
|
+
trigger: always_on
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
# Coding Standards - ${projectName}
|
|
363
422
|
|
|
364
423
|
${this.extractSection(this.outputs.prd || '', 'Code Quality') || ''}
|
|
365
424
|
|
|
@@ -403,7 +462,12 @@ Full requirements: \`.adf/sessions/${this.getSessionId()}/outputs/prd.md\`
|
|
|
403
462
|
let content;
|
|
404
463
|
|
|
405
464
|
if (this.framework === 'rapid') {
|
|
406
|
-
content =
|
|
465
|
+
content = `---
|
|
466
|
+
trigger: manual
|
|
467
|
+
description: Review project requirements before implementing
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
# Review Requirements
|
|
407
471
|
|
|
408
472
|
Use this workflow to review requirements before implementing.
|
|
409
473
|
|
|
@@ -424,7 +488,12 @@ Use this workflow to review requirements before implementing.
|
|
|
424
488
|
- How will success be measured?
|
|
425
489
|
`;
|
|
426
490
|
} else if (this.framework === 'balanced') {
|
|
427
|
-
content =
|
|
491
|
+
content = `---
|
|
492
|
+
trigger: manual
|
|
493
|
+
description: Review project requirements before implementing
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
# Review Requirements
|
|
428
497
|
|
|
429
498
|
Use this workflow to review requirements before implementing.
|
|
430
499
|
|
|
@@ -447,7 +516,12 @@ Use this workflow to review requirements before implementing.
|
|
|
447
516
|
- Are there any dependencies?
|
|
448
517
|
`;
|
|
449
518
|
} else {
|
|
450
|
-
content =
|
|
519
|
+
content = `---
|
|
520
|
+
trigger: manual
|
|
521
|
+
description: Review project requirements before implementing
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
# Review Requirements
|
|
451
525
|
|
|
452
526
|
Use this workflow to review requirements before implementing.
|
|
453
527
|
|
|
@@ -477,7 +551,12 @@ Use this workflow to review requirements before implementing.
|
|
|
477
551
|
let content;
|
|
478
552
|
|
|
479
553
|
if (this.framework === 'balanced') {
|
|
480
|
-
content =
|
|
554
|
+
content = `---
|
|
555
|
+
trigger: manual
|
|
556
|
+
description: Workflow for implementing a new feature
|
|
557
|
+
---
|
|
558
|
+
|
|
559
|
+
# Implement Feature
|
|
481
560
|
|
|
482
561
|
Use this workflow when implementing a feature.
|
|
483
562
|
|
|
@@ -511,7 +590,12 @@ Use this workflow when implementing a feature.
|
|
|
511
590
|
- Tasks: \`.adf/sessions/${this.getSessionId()}/outputs/tasks.md\`
|
|
512
591
|
`;
|
|
513
592
|
} else {
|
|
514
|
-
content =
|
|
593
|
+
content = `---
|
|
594
|
+
trigger: manual
|
|
595
|
+
description: Workflow for implementing a user story
|
|
596
|
+
---
|
|
597
|
+
|
|
598
|
+
# Implement User Story
|
|
515
599
|
|
|
516
600
|
Use this workflow when implementing a user story.
|
|
517
601
|
|
|
@@ -591,6 +675,132 @@ Use this workflow when implementing a user story.
|
|
|
591
675
|
return '0.3.0';
|
|
592
676
|
}
|
|
593
677
|
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* Load session answers from _progress.json
|
|
681
|
+
*/
|
|
682
|
+
async loadSessionAnswers() {
|
|
683
|
+
const fs = require('fs-extra');
|
|
684
|
+
const progressPath = path.join(this.sessionPath, '_progress.json');
|
|
685
|
+
|
|
686
|
+
try {
|
|
687
|
+
if (await fs.pathExists(progressPath)) {
|
|
688
|
+
const progress = await fs.readJson(progressPath);
|
|
689
|
+
return progress.answers || {};
|
|
690
|
+
}
|
|
691
|
+
} catch (error) {
|
|
692
|
+
// Fall back to empty if can't load
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
return {};
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* Parse implementation blueprint into structured sections
|
|
700
|
+
*/
|
|
701
|
+
parseImplementationBlueprint(blueprint, answers) {
|
|
702
|
+
const parsed = {
|
|
703
|
+
steps: null,
|
|
704
|
+
dataModel: null,
|
|
705
|
+
apiDesign: null,
|
|
706
|
+
errorHandling: null,
|
|
707
|
+
technicalApproach: null
|
|
708
|
+
};
|
|
709
|
+
|
|
710
|
+
// If blueprint exists, parse it
|
|
711
|
+
if (blueprint && blueprint.length > 20) {
|
|
712
|
+
parsed.steps = this.extractSubsection(blueprint, ['implementation steps', 'steps to implement', 'development steps']);
|
|
713
|
+
parsed.dataModel = this.extractSubsection(blueprint, ['data model', 'database schema', 'data structure']);
|
|
714
|
+
parsed.apiDesign = this.extractSubsection(blueprint, ['api design', 'api endpoints', 'routes']);
|
|
715
|
+
parsed.errorHandling = this.extractSubsection(blueprint, ['error handling', 'edge cases']);
|
|
716
|
+
parsed.technicalApproach = this.extractSubsection(blueprint, ['technical approach', 'architecture', 'approach']);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// If still empty, try to extract from answers
|
|
720
|
+
if (!parsed.steps && answers) {
|
|
721
|
+
// Look for tech stack, implementation details in any answer
|
|
722
|
+
const techStack = this.extractTechStackFromAnswers(answers);
|
|
723
|
+
const whatBuilding = this.extractWhatBuildingFromAnswers(answers);
|
|
724
|
+
|
|
725
|
+
if (techStack) {
|
|
726
|
+
parsed.technicalApproach = `**Tech Stack:**\n${techStack}`;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
if (whatBuilding) {
|
|
730
|
+
parsed.steps = `**Project Goal:**\n${whatBuilding}`;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
return parsed;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Extract subsection from content by looking for keywords
|
|
739
|
+
*/
|
|
740
|
+
extractSubsection(content, keywords) {
|
|
741
|
+
const lines = content.split('\n');
|
|
742
|
+
let inSection = false;
|
|
743
|
+
let sectionContent = [];
|
|
744
|
+
|
|
745
|
+
for (let i = 0; i < lines.length; i++) {
|
|
746
|
+
const line = lines[i];
|
|
747
|
+
const lowerLine = line.toLowerCase();
|
|
748
|
+
|
|
749
|
+
// Check if this line is a heading matching our keywords
|
|
750
|
+
if (line.match(/^#{2,4}\s+/)) {
|
|
751
|
+
const headingText = line.replace(/^#{2,4}\s+/, '').toLowerCase();
|
|
752
|
+
|
|
753
|
+
if (keywords.some(kw => headingText.includes(kw))) {
|
|
754
|
+
inSection = true;
|
|
755
|
+
continue;
|
|
756
|
+
} else if (inSection) {
|
|
757
|
+
// Hit a new heading, stop
|
|
758
|
+
break;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
if (inSection && line.trim()) {
|
|
763
|
+
sectionContent.push(line);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
const result = sectionContent.join('\n').trim();
|
|
768
|
+
return result.length > 10 ? result : null;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* Extract tech stack from any answer
|
|
773
|
+
*/
|
|
774
|
+
extractTechStackFromAnswers(answers) {
|
|
775
|
+
for (const [questionId, answer] of Object.entries(answers)) {
|
|
776
|
+
if (typeof answer === 'string') {
|
|
777
|
+
const lower = answer.toLowerCase();
|
|
778
|
+
// Look for mentions of frameworks, languages, databases
|
|
779
|
+
if (lower.includes('react') || lower.includes('vue') || lower.includes('angular') ||
|
|
780
|
+
lower.includes('node') || lower.includes('python') || lower.includes('next') ||
|
|
781
|
+
lower.includes('postgres') || lower.includes('mongo') || lower.includes('mysql')) {
|
|
782
|
+
return answer;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
return null;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
/**
|
|
790
|
+
* Extract "what are you building" from any answer
|
|
791
|
+
*/
|
|
792
|
+
extractWhatBuildingFromAnswers(answers) {
|
|
793
|
+
for (const [questionId, answer] of Object.entries(answers)) {
|
|
794
|
+
if (questionId.toLowerCase().includes('goal') ||
|
|
795
|
+
questionId.toLowerCase().includes('building') ||
|
|
796
|
+
questionId.toLowerCase().includes('project')) {
|
|
797
|
+
if (typeof answer === 'string' && answer.length > 20) {
|
|
798
|
+
return answer;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
return null;
|
|
803
|
+
}
|
|
594
804
|
}
|
|
595
805
|
|
|
596
806
|
module.exports = WindsurfGenerator;
|
package/package.json
CHANGED
|
Binary file
|