opencode-conductor-cdd-plugin 1.0.0-beta.13

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 (91) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +163 -0
  3. package/README.test.md +51 -0
  4. package/dist/commands/implement.d.ts +1 -0
  5. package/dist/commands/implement.js +30 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.js +108 -0
  8. package/dist/index.test.d.ts +1 -0
  9. package/dist/index.test.js +122 -0
  10. package/dist/prompts/agent/cdd.md +41 -0
  11. package/dist/prompts/agent/implementer.md +22 -0
  12. package/dist/prompts/agent.md +23 -0
  13. package/dist/prompts/cdd/implement.json +4 -0
  14. package/dist/prompts/cdd/newTrack.json +4 -0
  15. package/dist/prompts/cdd/revert.json +4 -0
  16. package/dist/prompts/cdd/setup.json +4 -0
  17. package/dist/prompts/cdd/setup.test.d.ts +1 -0
  18. package/dist/prompts/cdd/setup.test.js +132 -0
  19. package/dist/prompts/cdd/setup.test.ts +168 -0
  20. package/dist/prompts/cdd/status.json +4 -0
  21. package/dist/prompts/strategies/delegate.md +11 -0
  22. package/dist/prompts/strategies/manual.md +9 -0
  23. package/dist/templates/code_styleguides/c.md +28 -0
  24. package/dist/templates/code_styleguides/cpp.md +46 -0
  25. package/dist/templates/code_styleguides/csharp.md +115 -0
  26. package/dist/templates/code_styleguides/dart.md +238 -0
  27. package/dist/templates/code_styleguides/general.md +23 -0
  28. package/dist/templates/code_styleguides/go.md +48 -0
  29. package/dist/templates/code_styleguides/html-css.md +49 -0
  30. package/dist/templates/code_styleguides/java.md +39 -0
  31. package/dist/templates/code_styleguides/javascript.md +51 -0
  32. package/dist/templates/code_styleguides/julia.md +27 -0
  33. package/dist/templates/code_styleguides/kotlin.md +41 -0
  34. package/dist/templates/code_styleguides/php.md +37 -0
  35. package/dist/templates/code_styleguides/python.md +37 -0
  36. package/dist/templates/code_styleguides/react.md +37 -0
  37. package/dist/templates/code_styleguides/ruby.md +39 -0
  38. package/dist/templates/code_styleguides/rust.md +44 -0
  39. package/dist/templates/code_styleguides/shell.md +35 -0
  40. package/dist/templates/code_styleguides/solidity.md +60 -0
  41. package/dist/templates/code_styleguides/sql.md +39 -0
  42. package/dist/templates/code_styleguides/swift.md +36 -0
  43. package/dist/templates/code_styleguides/typescript.md +43 -0
  44. package/dist/templates/code_styleguides/vue.md +38 -0
  45. package/dist/templates/code_styleguides/zig.md +27 -0
  46. package/dist/templates/workflow.md +336 -0
  47. package/dist/tools/background.d.ts +54 -0
  48. package/dist/tools/background.js +198 -0
  49. package/dist/tools/commands.d.ts +11 -0
  50. package/dist/tools/commands.js +80 -0
  51. package/dist/tools/commands.test.d.ts +1 -0
  52. package/dist/tools/commands.test.js +142 -0
  53. package/dist/tools/delegate.d.ts +3 -0
  54. package/dist/tools/delegate.js +45 -0
  55. package/dist/utils/autogenerateFlow.d.ts +65 -0
  56. package/dist/utils/autogenerateFlow.js +391 -0
  57. package/dist/utils/autogenerateFlow.test.d.ts +1 -0
  58. package/dist/utils/autogenerateFlow.test.js +610 -0
  59. package/dist/utils/bootstrap.d.ts +1 -0
  60. package/dist/utils/bootstrap.js +46 -0
  61. package/dist/utils/commandFactory.d.ts +11 -0
  62. package/dist/utils/commandFactory.js +69 -0
  63. package/dist/utils/commitMessages.d.ts +35 -0
  64. package/dist/utils/commitMessages.js +33 -0
  65. package/dist/utils/commitMessages.test.d.ts +1 -0
  66. package/dist/utils/commitMessages.test.js +79 -0
  67. package/dist/utils/configDetection.d.ts +7 -0
  68. package/dist/utils/configDetection.js +49 -0
  69. package/dist/utils/configDetection.test.d.ts +1 -0
  70. package/dist/utils/configDetection.test.js +119 -0
  71. package/dist/utils/contentGeneration.d.ts +10 -0
  72. package/dist/utils/contentGeneration.js +141 -0
  73. package/dist/utils/contentGeneration.test.d.ts +1 -0
  74. package/dist/utils/contentGeneration.test.js +147 -0
  75. package/dist/utils/contextAnalysis.d.ts +100 -0
  76. package/dist/utils/contextAnalysis.js +308 -0
  77. package/dist/utils/contextAnalysis.test.d.ts +1 -0
  78. package/dist/utils/contextAnalysis.test.js +307 -0
  79. package/dist/utils/gitNotes.d.ts +23 -0
  80. package/dist/utils/gitNotes.js +53 -0
  81. package/dist/utils/gitNotes.test.d.ts +1 -0
  82. package/dist/utils/gitNotes.test.js +105 -0
  83. package/dist/utils/ignoreMatcher.d.ts +9 -0
  84. package/dist/utils/ignoreMatcher.js +77 -0
  85. package/dist/utils/ignoreMatcher.test.d.ts +1 -0
  86. package/dist/utils/ignoreMatcher.test.js +126 -0
  87. package/dist/utils/stateManager.d.ts +10 -0
  88. package/dist/utils/stateManager.js +30 -0
  89. package/package.json +90 -0
  90. package/scripts/convert-legacy.cjs +17 -0
  91. package/scripts/postinstall.cjs +38 -0
@@ -0,0 +1,391 @@
1
+ import { generateProductGuide, generateProductGuidelines, generateTechStack, generateWorkflow, } from './contentGeneration.js';
2
+ export const MAX_REGENERATION_ATTEMPTS = 3;
3
+ export const MIN_CONTEXT_SIGNALS = 2;
4
+ export const MIN_CONFIDENCE_THRESHOLD = 0.4;
5
+ export function createInitialState(questionId) {
6
+ return {
7
+ questionId,
8
+ attemptNumber: 1,
9
+ status: 'generating',
10
+ content: '',
11
+ userChoice: null,
12
+ guidanceHistory: [],
13
+ editHistory: [],
14
+ timestamp: new Date().toISOString(),
15
+ };
16
+ }
17
+ export function generateContentForSection(sectionType, context) {
18
+ try {
19
+ let generationResult;
20
+ switch (sectionType) {
21
+ case 'product_guide':
22
+ generationResult = generateProductGuide(context);
23
+ break;
24
+ case 'product_guidelines':
25
+ generationResult = generateProductGuidelines(context);
26
+ break;
27
+ case 'tech_stack':
28
+ generationResult = generateTechStack(context);
29
+ break;
30
+ case 'workflow':
31
+ generationResult = generateWorkflow(context);
32
+ break;
33
+ default:
34
+ return { success: false, error: `Unknown section type: ${sectionType}` };
35
+ }
36
+ if (generationResult.confidence < MIN_CONFIDENCE_THRESHOLD) {
37
+ const sufficiency = evaluateContextSufficiency(context);
38
+ const ambiguity = evaluateAmbiguity(context);
39
+ const error = 'Insufficient context for reliable autogeneration';
40
+ const failureSummary = formatAutogenerationFailure(sectionType, error, sufficiency, ambiguity);
41
+ const fallbackPrompt = formatFallbackPrompt(error, sufficiency.missing);
42
+ return {
43
+ success: false,
44
+ error,
45
+ failureSummary,
46
+ fallbackPrompt,
47
+ fallbackAction: resolveFallbackAction(null),
48
+ fallbackState: sufficiency,
49
+ ambiguityState: ambiguity,
50
+ };
51
+ }
52
+ return {
53
+ success: true,
54
+ content: generationResult.content,
55
+ };
56
+ }
57
+ catch (error) {
58
+ const message = error instanceof Error ? error.message : 'Unknown error during generation';
59
+ const sufficiency = evaluateContextSufficiency(context);
60
+ const ambiguity = evaluateAmbiguity(context);
61
+ const failureSummary = formatAutogenerationFailure(sectionType, message, sufficiency, ambiguity);
62
+ const fallbackPrompt = formatFallbackPrompt(message, sufficiency.missing);
63
+ return {
64
+ success: false,
65
+ error: message,
66
+ failureSummary,
67
+ fallbackPrompt,
68
+ fallbackAction: resolveFallbackAction(null),
69
+ fallbackState: sufficiency,
70
+ ambiguityState: ambiguity,
71
+ };
72
+ }
73
+ }
74
+ export function validateContent(content, sectionType) {
75
+ if (!content || content.trim().length === 0) {
76
+ return { valid: false, error: 'Content cannot be empty' };
77
+ }
78
+ const trimmedContent = content.trim();
79
+ switch (sectionType) {
80
+ case 'product_guide':
81
+ case 'product_guidelines':
82
+ if (trimmedContent.length < 20) {
83
+ return { valid: false, error: 'Content must be at least 20 characters' };
84
+ }
85
+ if (!/[a-zA-Z]{3,}/.test(trimmedContent)) {
86
+ return { valid: false, error: 'Content must contain coherent text' };
87
+ }
88
+ break;
89
+ case 'tech_stack':
90
+ if (trimmedContent.length < 5) {
91
+ return { valid: false, error: 'Tech stack must mention at least one technology' };
92
+ }
93
+ break;
94
+ case 'workflow':
95
+ if (trimmedContent.length < 30) {
96
+ return { valid: false, error: 'Workflow description must be at least 30 characters' };
97
+ }
98
+ break;
99
+ }
100
+ return { valid: true };
101
+ }
102
+ export function evaluateContextSufficiency(context) {
103
+ const missing = [];
104
+ const signals = [];
105
+ const hasManifests = context.raw.manifests.length > 0;
106
+ const hasDocs = context.raw.docs.length > 0;
107
+ const hasGit = context.raw.git.commitCount > 0;
108
+ const hasStructure = context.raw.structure.structure.length > 0;
109
+ const hasIgnores = context.raw.ignores.patterns.length > 0;
110
+ const hasCicd = context.raw.cicd.length > 0;
111
+ if (!hasManifests)
112
+ missing.push('manifest files');
113
+ if (!hasDocs)
114
+ missing.push('documentation');
115
+ if (!hasGit)
116
+ missing.push('git history');
117
+ if (!hasStructure)
118
+ missing.push('source structure');
119
+ if (!hasIgnores)
120
+ missing.push('ignore patterns');
121
+ if (!hasCicd)
122
+ missing.push('CI/CD configuration');
123
+ if (hasManifests)
124
+ signals.push('manifests');
125
+ if (hasDocs)
126
+ signals.push('docs');
127
+ if (hasGit)
128
+ signals.push('git');
129
+ if (hasStructure)
130
+ signals.push('structure');
131
+ if (hasIgnores)
132
+ signals.push('ignores');
133
+ if (hasCicd)
134
+ signals.push('cicd');
135
+ if (signals.length >= MIN_CONTEXT_SIGNALS) {
136
+ return {
137
+ sufficient: true,
138
+ reason: `Detected ${signals.length} context sources: ${signals.join(', ')}`,
139
+ missing,
140
+ };
141
+ }
142
+ return {
143
+ sufficient: false,
144
+ reason: 'Not enough project context sources to autogenerate reliably',
145
+ missing,
146
+ };
147
+ }
148
+ export function formatAutogenerationFailure(sectionType, error, sufficiency, ambiguity) {
149
+ const missingList = sufficiency.missing.length > 0
150
+ ? `Missing: ${sufficiency.missing.join(', ')}`
151
+ : 'Missing: none detected';
152
+ const ambiguityList = ambiguity.signals.length > 0
153
+ ? `Ambiguity signals: ${ambiguity.signals.join('; ')}`
154
+ : 'Ambiguity signals: none';
155
+ return `Autogeneration failed for ${sectionType}.
156
+ Reason: ${error}
157
+ ${sufficiency.reason}
158
+ ${missingList}
159
+ ${ambiguityList}`;
160
+ }
161
+ export function evaluateAmbiguity(context) {
162
+ const signals = [];
163
+ const warnings = context.meta.warnings;
164
+ if (warnings.some((warning) => warning.toLowerCase().includes('no manifest'))) {
165
+ signals.push('Missing manifest files');
166
+ }
167
+ if (warnings.some((warning) => warning.toLowerCase().includes('no readme'))) {
168
+ signals.push('Missing README documentation');
169
+ }
170
+ if (context.insights.projectType === 'unknown') {
171
+ signals.push('Unknown project type');
172
+ }
173
+ if (context.insights.techStack.languages.length === 0) {
174
+ signals.push('No dominant language detected');
175
+ }
176
+ if (context.meta.filesAnalyzed === 0) {
177
+ signals.push('No files analyzed');
178
+ }
179
+ if (signals.length === 0) {
180
+ return { ambiguous: false, reason: 'Context appears coherent', signals };
181
+ }
182
+ return {
183
+ ambiguous: true,
184
+ reason: 'Project context appears ambiguous or incomplete',
185
+ signals,
186
+ };
187
+ }
188
+ export function formatFallbackPrompt(reason, missing) {
189
+ const missingList = missing.length > 0
190
+ ? `Missing: ${missing.join(', ')}`
191
+ : 'No specific missing data identified.';
192
+ return `Autogeneration could not proceed. ${reason}
193
+
194
+ ${missingList}
195
+
196
+ Please choose how to continue:
197
+ A) Continue with manual Q&A
198
+ B) Provide more context for regeneration
199
+ C) Accept partial results (use what was generated)
200
+
201
+ Please enter A, B, or C:`;
202
+ }
203
+ export function parseFallbackChoice(input) {
204
+ const normalized = input.trim().toUpperCase();
205
+ if (['A', 'MANUAL', 'M'].includes(normalized)) {
206
+ return 'A';
207
+ }
208
+ if (['B', 'CONTEXT', 'REGENERATE', 'R'].includes(normalized)) {
209
+ return 'B';
210
+ }
211
+ if (['C', 'PARTIAL', 'ACCEPT'].includes(normalized)) {
212
+ return 'C';
213
+ }
214
+ return null;
215
+ }
216
+ export function resolveFallbackAction(choice) {
217
+ switch (choice) {
218
+ case 'A':
219
+ return 'manual';
220
+ case 'B':
221
+ return 'regenerate';
222
+ case 'C':
223
+ return 'accept_partial';
224
+ default:
225
+ return 'manual';
226
+ }
227
+ }
228
+ export function handleAccept(state, sectionType) {
229
+ const validation = validateContent(state.content, sectionType);
230
+ if (!validation.valid) {
231
+ return { success: false, error: validation.error };
232
+ }
233
+ const updatedState = {
234
+ ...state,
235
+ status: 'accepted',
236
+ userChoice: 'A',
237
+ timestamp: new Date().toISOString(),
238
+ };
239
+ return {
240
+ success: true,
241
+ content: state.content,
242
+ state: updatedState,
243
+ };
244
+ }
245
+ export function handleEdit(state, editedContent, sectionType) {
246
+ const validation = validateContent(editedContent, sectionType);
247
+ if (!validation.valid) {
248
+ return { success: false, error: validation.error };
249
+ }
250
+ const updatedState = {
251
+ ...state,
252
+ status: 'edited',
253
+ userChoice: 'B',
254
+ content: editedContent,
255
+ editHistory: [...state.editHistory, editedContent],
256
+ timestamp: new Date().toISOString(),
257
+ };
258
+ return {
259
+ success: true,
260
+ content: editedContent,
261
+ state: updatedState,
262
+ };
263
+ }
264
+ export function handleRegenerate(state, guidance, sectionType, context) {
265
+ if (!guidance || guidance.trim().length < 5) {
266
+ return { success: false, error: 'Guidance must be at least 5 characters' };
267
+ }
268
+ if (state.attemptNumber >= MAX_REGENERATION_ATTEMPTS) {
269
+ return {
270
+ success: false,
271
+ error: `Maximum regeneration attempts (${MAX_REGENERATION_ATTEMPTS}) reached`,
272
+ };
273
+ }
274
+ const updatedState = {
275
+ ...state,
276
+ status: 'regenerating',
277
+ userChoice: 'C',
278
+ attemptNumber: state.attemptNumber + 1,
279
+ guidanceHistory: [...state.guidanceHistory, guidance],
280
+ timestamp: new Date().toISOString(),
281
+ };
282
+ const generationResult = generateContentForSection(sectionType, context);
283
+ if (!generationResult.success) {
284
+ return {
285
+ success: false,
286
+ error: generationResult.error,
287
+ state: updatedState,
288
+ };
289
+ }
290
+ const finalState = {
291
+ ...updatedState,
292
+ status: 'presented',
293
+ content: generationResult.content || '',
294
+ };
295
+ return {
296
+ success: true,
297
+ content: generationResult.content,
298
+ state: finalState,
299
+ };
300
+ }
301
+ export function formatPresentationPrompt(content) {
302
+ return `---
303
+
304
+ I've analyzed your project and autogenerated the following content:
305
+
306
+ ${content}
307
+
308
+ ---
309
+
310
+ **Please review the autogenerated content above.**
311
+
312
+ What would you like to do?
313
+ A) Accept - Use this content and proceed to the next question
314
+ B) Edit - Make manual changes to the generated content
315
+ C) Regenerate - Ask me to generate different content with your guidance
316
+
317
+ Please enter A, B, or C:`;
318
+ }
319
+ export function formatEditPrompt(content) {
320
+ return `You selected Edit. I'll present the autogenerated content below. Please provide your edited version.
321
+
322
+ You can:
323
+ - Modify any part of the content
324
+ - Add new sections
325
+ - Remove sections you don't want
326
+ - Completely rewrite it
327
+
328
+ ---
329
+ Current content:
330
+ ${content}
331
+ ---
332
+
333
+ Please paste your edited version below (type 'cancel' to go back to options):`;
334
+ }
335
+ export function formatRegeneratePrompt() {
336
+ return `You selected Regenerate. To generate better content, please provide guidance.
337
+
338
+ What would you like me to change or focus on? (Examples: "Focus more on X", "Remove mention of Y", "Use simpler language", "Be more specific about Z")
339
+
340
+ Your guidance (type 'cancel' to go back):`;
341
+ }
342
+ export function formatMaxAttemptsPrompt() {
343
+ return `You've regenerated content ${MAX_REGENERATION_ATTEMPTS} times. It seems autogeneration isn't working well for this question. Would you like to:
344
+
345
+ A) Accept the current version
346
+ B) Edit the current version manually
347
+ C) Switch to manual Q&A for this question (I'll ask specific questions)
348
+
349
+ Please enter A, B, or C:`;
350
+ }
351
+ export function parseUserChoice(input) {
352
+ const normalized = input.trim().toUpperCase();
353
+ if (['A', 'ACCEPT', 'YES', 'Y'].includes(normalized)) {
354
+ return 'A';
355
+ }
356
+ if (['B', 'EDIT', 'E'].includes(normalized)) {
357
+ return 'B';
358
+ }
359
+ if (['C', 'REGENERATE', 'R'].includes(normalized)) {
360
+ return 'C';
361
+ }
362
+ return null;
363
+ }
364
+ export function isCancel(input) {
365
+ return input.trim().toLowerCase() === 'cancel';
366
+ }
367
+ export function handleFallbackManual(sectionType, reason) {
368
+ return {
369
+ success: false,
370
+ error: `Fallback to manual Q&A: ${reason}`,
371
+ fallbackAction: 'manual',
372
+ };
373
+ }
374
+ export function handleFallbackAcceptPartial(partialContent, sectionType, reason) {
375
+ const validation = validateContent(partialContent, sectionType);
376
+ if (!validation.valid) {
377
+ return {
378
+ success: false,
379
+ error: `Partial content is invalid: ${validation.error}. Falling back to manual Q&A.`,
380
+ fallbackAction: 'manual',
381
+ };
382
+ }
383
+ return {
384
+ success: true,
385
+ content: partialContent,
386
+ fallbackAction: 'accept_partial',
387
+ };
388
+ }
389
+ export function handleFallbackRegenerate(sectionType, context, additionalContext) {
390
+ return generateContentForSection(sectionType, context);
391
+ }
@@ -0,0 +1 @@
1
+ export {};