@specsafe/core 0.4.0 → 0.6.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 (157) hide show
  1. package/dist/agents/adapters/base.d.ts +44 -0
  2. package/dist/agents/adapters/base.d.ts.map +1 -0
  3. package/dist/agents/adapters/base.js +164 -0
  4. package/dist/agents/adapters/base.js.map +1 -0
  5. package/dist/agents/adapters/claude-code.d.ts +14 -0
  6. package/dist/agents/adapters/claude-code.d.ts.map +1 -0
  7. package/dist/agents/adapters/claude-code.js +120 -0
  8. package/dist/agents/adapters/claude-code.js.map +1 -0
  9. package/dist/agents/adapters/copilot.d.ts +13 -0
  10. package/dist/agents/adapters/copilot.d.ts.map +1 -0
  11. package/dist/agents/adapters/copilot.js +115 -0
  12. package/dist/agents/adapters/copilot.js.map +1 -0
  13. package/dist/agents/adapters/cursor.d.ts +13 -0
  14. package/dist/agents/adapters/cursor.d.ts.map +1 -0
  15. package/dist/agents/adapters/cursor.js +105 -0
  16. package/dist/agents/adapters/cursor.js.map +1 -0
  17. package/dist/agents/adapters/gemini-cli.d.ts +13 -0
  18. package/dist/agents/adapters/gemini-cli.d.ts.map +1 -0
  19. package/dist/agents/adapters/gemini-cli.js +79 -0
  20. package/dist/agents/adapters/gemini-cli.js.map +1 -0
  21. package/dist/agents/adapters/index.d.ts +16 -0
  22. package/dist/agents/adapters/index.d.ts.map +1 -0
  23. package/dist/agents/adapters/index.js +47 -0
  24. package/dist/agents/adapters/index.js.map +1 -0
  25. package/dist/agents/adapters/opencode.d.ts +13 -0
  26. package/dist/agents/adapters/opencode.d.ts.map +1 -0
  27. package/dist/agents/adapters/opencode.js +67 -0
  28. package/dist/agents/adapters/opencode.js.map +1 -0
  29. package/dist/agents/index.d.ts +8 -0
  30. package/dist/agents/index.d.ts.map +1 -0
  31. package/dist/agents/index.js +9 -0
  32. package/dist/agents/index.js.map +1 -0
  33. package/dist/agents/registry.d.ts +70 -0
  34. package/dist/agents/registry.d.ts.map +1 -0
  35. package/dist/agents/registry.js +194 -0
  36. package/dist/agents/registry.js.map +1 -0
  37. package/dist/agents/types.d.ts +71 -0
  38. package/dist/agents/types.d.ts.map +1 -0
  39. package/dist/agents/types.js +6 -0
  40. package/dist/agents/types.js.map +1 -0
  41. package/dist/delta/merger.d.ts +36 -0
  42. package/dist/delta/merger.d.ts.map +1 -0
  43. package/dist/delta/merger.js +264 -0
  44. package/dist/delta/merger.js.map +1 -0
  45. package/dist/delta/parser.d.ts +27 -0
  46. package/dist/delta/parser.d.ts.map +1 -0
  47. package/dist/delta/parser.js +196 -0
  48. package/dist/delta/parser.js.map +1 -0
  49. package/dist/delta/types.d.ts +39 -0
  50. package/dist/delta/types.d.ts.map +1 -0
  51. package/dist/delta/types.js +6 -0
  52. package/dist/delta/types.js.map +1 -0
  53. package/dist/ears/index.d.ts +11 -0
  54. package/dist/ears/index.d.ts.map +1 -0
  55. package/dist/ears/index.js +11 -0
  56. package/dist/ears/index.js.map +1 -0
  57. package/dist/ears/parser.d.ts +22 -0
  58. package/dist/ears/parser.d.ts.map +1 -0
  59. package/dist/ears/parser.js +273 -0
  60. package/dist/ears/parser.js.map +1 -0
  61. package/dist/ears/template.d.ts +20 -0
  62. package/dist/ears/template.d.ts.map +1 -0
  63. package/dist/ears/template.js +364 -0
  64. package/dist/ears/template.js.map +1 -0
  65. package/dist/ears/types.d.ts +58 -0
  66. package/dist/ears/types.d.ts.map +1 -0
  67. package/dist/ears/types.js +6 -0
  68. package/dist/ears/types.js.map +1 -0
  69. package/dist/ears/validator.d.ts +37 -0
  70. package/dist/ears/validator.d.ts.map +1 -0
  71. package/dist/ears/validator.js +234 -0
  72. package/dist/ears/validator.js.map +1 -0
  73. package/dist/elicitation/engine.d.ts +75 -0
  74. package/dist/elicitation/engine.d.ts.map +1 -0
  75. package/dist/elicitation/engine.js +174 -0
  76. package/dist/elicitation/engine.js.map +1 -0
  77. package/dist/elicitation/flows.d.ts +18 -0
  78. package/dist/elicitation/flows.d.ts.map +1 -0
  79. package/dist/elicitation/flows.js +331 -0
  80. package/dist/elicitation/flows.js.map +1 -0
  81. package/dist/elicitation/generator.d.ts +20 -0
  82. package/dist/elicitation/generator.d.ts.map +1 -0
  83. package/dist/elicitation/generator.js +260 -0
  84. package/dist/elicitation/generator.js.map +1 -0
  85. package/dist/elicitation/index.d.ts +27 -0
  86. package/dist/elicitation/index.d.ts.map +1 -0
  87. package/dist/elicitation/index.js +29 -0
  88. package/dist/elicitation/index.js.map +1 -0
  89. package/dist/elicitation/types.d.ts +69 -0
  90. package/dist/elicitation/types.d.ts.map +1 -0
  91. package/dist/elicitation/types.js +6 -0
  92. package/dist/elicitation/types.js.map +1 -0
  93. package/dist/extensions/builtins/complexity.d.ts +7 -0
  94. package/dist/extensions/builtins/complexity.d.ts.map +1 -0
  95. package/dist/extensions/builtins/complexity.js +97 -0
  96. package/dist/extensions/builtins/complexity.js.map +1 -0
  97. package/dist/extensions/builtins/owasp.d.ts +7 -0
  98. package/dist/extensions/builtins/owasp.d.ts.map +1 -0
  99. package/dist/extensions/builtins/owasp.js +76 -0
  100. package/dist/extensions/builtins/owasp.js.map +1 -0
  101. package/dist/extensions/index.d.ts +54 -0
  102. package/dist/extensions/index.d.ts.map +1 -0
  103. package/dist/extensions/index.js +72 -0
  104. package/dist/extensions/index.js.map +1 -0
  105. package/dist/extensions/loader.d.ts +28 -0
  106. package/dist/extensions/loader.d.ts.map +1 -0
  107. package/dist/extensions/loader.js +62 -0
  108. package/dist/extensions/loader.js.map +1 -0
  109. package/dist/extensions/registry.d.ts +74 -0
  110. package/dist/extensions/registry.d.ts.map +1 -0
  111. package/dist/extensions/registry.js +159 -0
  112. package/dist/extensions/registry.js.map +1 -0
  113. package/dist/extensions/types.d.ts +70 -0
  114. package/dist/extensions/types.d.ts.map +1 -0
  115. package/dist/extensions/types.js +2 -0
  116. package/dist/extensions/types.js.map +1 -0
  117. package/dist/governance/builtins.d.ts +7 -0
  118. package/dist/governance/builtins.d.ts.map +1 -0
  119. package/dist/governance/builtins.js +105 -0
  120. package/dist/governance/builtins.js.map +1 -0
  121. package/dist/governance/constitution.d.ts +23 -0
  122. package/dist/governance/constitution.d.ts.map +1 -0
  123. package/dist/governance/constitution.js +245 -0
  124. package/dist/governance/constitution.js.map +1 -0
  125. package/dist/governance/index.d.ts +3 -0
  126. package/dist/governance/index.d.ts.map +1 -0
  127. package/dist/governance/index.js +2 -0
  128. package/dist/governance/index.js.map +1 -0
  129. package/dist/governance/template.d.ts +12 -0
  130. package/dist/governance/template.d.ts.map +1 -0
  131. package/dist/governance/template.js +84 -0
  132. package/dist/governance/template.js.map +1 -0
  133. package/dist/governance/types.d.ts +64 -0
  134. package/dist/governance/types.d.ts.map +1 -0
  135. package/dist/governance/types.js +2 -0
  136. package/dist/governance/types.js.map +1 -0
  137. package/dist/index.d.ts +23 -18
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/index.js +17 -18
  140. package/dist/index.js.map +1 -1
  141. package/dist/templates/checklist.d.ts +7 -0
  142. package/dist/templates/checklist.d.ts.map +1 -0
  143. package/dist/templates/checklist.js +131 -0
  144. package/dist/templates/checklist.js.map +1 -0
  145. package/dist/templates/delta-template.d.ts +18 -0
  146. package/dist/templates/delta-template.d.ts.map +1 -0
  147. package/dist/templates/delta-template.js +191 -0
  148. package/dist/templates/delta-template.js.map +1 -0
  149. package/dist/templates/engine.d.ts +20 -0
  150. package/dist/templates/engine.d.ts.map +1 -0
  151. package/dist/templates/engine.js +187 -0
  152. package/dist/templates/engine.js.map +1 -0
  153. package/dist/templates/types.d.ts +67 -0
  154. package/dist/templates/types.d.ts.map +1 -0
  155. package/dist/templates/types.js +5 -0
  156. package/dist/templates/types.js.map +1 -0
  157. package/package.json +1 -1
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Elicitation System
3
+ *
4
+ * Interactive specification elicitation workflows for SpecSafe.
5
+ * Guides users through structured question flows to create well-formed specs.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { ElicitationEngine, quickFlow, generateSpec } from '@specsafe/core';
10
+ *
11
+ * const engine = new ElicitationEngine(quickFlow);
12
+ * let step = engine.start();
13
+ *
14
+ * while (step) {
15
+ * const answer = await promptUser(step);
16
+ * step = engine.answer(step.id, answer);
17
+ * }
18
+ *
19
+ * const result = engine.getResult();
20
+ * const spec = generateSpec(result);
21
+ * ```
22
+ */
23
+ // Export engine
24
+ export { ElicitationEngine } from './engine.js';
25
+ // Export built-in flows
26
+ export { quickFlow, fullFlow, earsFlow } from './flows.js';
27
+ // Export generator
28
+ export { generateSpec } from './generator.js';
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/elicitation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAYH,gBAAgB;AAChB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,wBAAwB;AACxB,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3D,mBAAmB;AACnB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Elicitation System Types
3
+ * Defines interactive specification elicitation workflows
4
+ */
5
+ /**
6
+ * Step types for elicitation flows
7
+ */
8
+ export type StepType = 'text' | 'choice' | 'multi-choice' | 'confirm' | 'conditional';
9
+ /**
10
+ * Validation function for step answers
11
+ */
12
+ export type ValidateFn = (value: any) => boolean | string;
13
+ /**
14
+ * Condition function to determine if step should be shown
15
+ */
16
+ export type ConditionFn = (answers: Record<string, any>) => boolean;
17
+ /**
18
+ * Individual step in an elicitation flow
19
+ */
20
+ export interface ElicitationStep {
21
+ /** Unique step identifier */
22
+ id: string;
23
+ /** Prompt text to display to user */
24
+ prompt: string;
25
+ /** Step type */
26
+ type: StepType;
27
+ /** Available choices (for choice/multi-choice types) */
28
+ choices?: string[];
29
+ /** Default value */
30
+ default?: any;
31
+ /** Whether this step is required */
32
+ required?: boolean;
33
+ /** Validation function */
34
+ validate?: ValidateFn;
35
+ /** Condition function to determine if step should be shown */
36
+ condition?: ConditionFn;
37
+ }
38
+ /**
39
+ * Complete elicitation flow definition
40
+ */
41
+ export interface ElicitationFlow {
42
+ /** Unique flow identifier */
43
+ id: string;
44
+ /** Human-readable flow name */
45
+ name: string;
46
+ /** Flow description */
47
+ description: string;
48
+ /** Steps in the flow */
49
+ steps: ElicitationStep[];
50
+ }
51
+ /**
52
+ * Result of completed elicitation flow
53
+ */
54
+ export interface ElicitationResult {
55
+ /** ID of the flow that was completed */
56
+ flowId: string;
57
+ /** User answers keyed by step ID */
58
+ answers: Record<string, any>;
59
+ /** Metadata about the elicitation session */
60
+ metadata: {
61
+ /** When the elicitation started */
62
+ startedAt: Date;
63
+ /** When the elicitation completed */
64
+ completedAt: Date;
65
+ /** Step IDs that were skipped */
66
+ skipped: string[];
67
+ };
68
+ }
69
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/elicitation/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAChB,MAAM,GACN,QAAQ,GACR,cAAc,GACd,SAAS,GACT,aAAa,CAAC;AAElB;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,GAAG,MAAM,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,EAAE,EAAE,MAAM,CAAC;IAEX,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IAEf,gBAAgB;IAChB,IAAI,EAAE,QAAQ,CAAC;IAEf,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnB,oBAAoB;IACpB,OAAO,CAAC,EAAE,GAAG,CAAC;IAEd,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,UAAU,CAAC;IAEtB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,WAAW,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,EAAE,EAAE,MAAM,CAAC;IAEX,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IAEb,uBAAuB;IACvB,WAAW,EAAE,MAAM,CAAC;IAEpB,wBAAwB;IACxB,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IAEf,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE7B,6CAA6C;IAC7C,QAAQ,EAAE;QACR,mCAAmC;QACnC,SAAS,EAAE,IAAI,CAAC;QAEhB,qCAAqC;QACrC,WAAW,EAAE,IAAI,CAAC;QAElB,iCAAiC;QACjC,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;CACH"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Elicitation System Types
3
+ * Defines interactive specification elicitation workflows
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/elicitation/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,7 @@
1
+ import type { Extension } from '../types.js';
2
+ /**
3
+ * Complexity Scorer Extension
4
+ * Analyzes spec complexity based on various factors
5
+ */
6
+ export declare const complexityExtension: Extension;
7
+ //# sourceMappingURL=complexity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"complexity.d.ts","sourceRoot":"","sources":["../../../src/extensions/builtins/complexity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAqC,MAAM,aAAa,CAAC;AAShF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAwGjC,CAAC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Escape special regex characters
3
+ */
4
+ function escapeRegex(str) {
5
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
6
+ }
7
+ /**
8
+ * Complexity Scorer Extension
9
+ * Analyzes spec complexity based on various factors
10
+ */
11
+ export const complexityExtension = {
12
+ id: 'complexity-scorer',
13
+ name: 'Complexity Scorer',
14
+ description: 'Analyzes and scores spec complexity',
15
+ version: '1.0.0',
16
+ author: 'SpecSafe Team',
17
+ enabled: true,
18
+ hooks: {
19
+ 'post-validate': (context) => {
20
+ const { spec } = context;
21
+ const warnings = [];
22
+ const suggestions = [];
23
+ // Calculate complexity factors
24
+ const requirementCount = spec.requirements.length;
25
+ const scenarioCount = spec.requirements.reduce((sum, req) => sum + (req.scenarios?.length || 0), 0);
26
+ // Count integration points (mentions of external systems)
27
+ const descLower = spec.description.toLowerCase();
28
+ const integrationKeywords = ['api', 'service', 'integration', 'external', 'third-party', 'webhook'];
29
+ const integrationPoints = integrationKeywords.filter(keyword => new RegExp(`\\b${escapeRegex(keyword)}\\b`, 'i').test(descLower)).length;
30
+ // Count dependencies (mentions of other systems/modules)
31
+ const dependencyKeywords = ['depends', 'requires', 'dependency', 'module', 'component'];
32
+ const dependencies = dependencyKeywords.filter(keyword => new RegExp(`\\b${escapeRegex(keyword)}\\b`, 'i').test(descLower)).length;
33
+ // Calculate complexity score (0-100)
34
+ let complexityScore = 0;
35
+ // Requirements contribute up to 40 points
36
+ complexityScore += Math.min(requirementCount * 4, 40);
37
+ // Scenarios contribute up to 30 points
38
+ complexityScore += Math.min(scenarioCount * 2, 30);
39
+ // Integration points contribute up to 15 points
40
+ complexityScore += Math.min(integrationPoints * 5, 15);
41
+ // Dependencies contribute up to 15 points
42
+ complexityScore += Math.min(dependencies * 5, 15);
43
+ // Determine complexity level
44
+ let complexityLevel;
45
+ if (complexityScore < 25) {
46
+ complexityLevel = 'low';
47
+ }
48
+ else if (complexityScore < 50) {
49
+ complexityLevel = 'medium';
50
+ }
51
+ else if (complexityScore < 75) {
52
+ complexityLevel = 'high';
53
+ }
54
+ else {
55
+ complexityLevel = 'very-high';
56
+ }
57
+ // Generate warnings and suggestions
58
+ if (requirementCount > 10) {
59
+ warnings.push(`High requirement count: ${requirementCount}`);
60
+ suggestions.push('Consider breaking this spec into smaller, focused specs');
61
+ }
62
+ if (scenarioCount > 20) {
63
+ warnings.push(`High scenario count: ${scenarioCount}`);
64
+ suggestions.push('Review if all scenarios are necessary or can be simplified');
65
+ }
66
+ if (integrationPoints > 3) {
67
+ warnings.push(`Many integration points detected: ${integrationPoints}`);
68
+ suggestions.push('Consider documenting integration architecture separately');
69
+ }
70
+ if (complexityLevel === 'very-high') {
71
+ warnings.push('Very high complexity detected');
72
+ suggestions.push('Break this spec into multiple smaller specs for better maintainability');
73
+ }
74
+ const message = `Complexity: ${complexityLevel} (score: ${complexityScore}/100)`;
75
+ const emoji = complexityLevel === 'low' ? '✓' :
76
+ complexityLevel === 'medium' ? '⚡' :
77
+ complexityLevel === 'high' ? '⚠️' : '🔴';
78
+ return {
79
+ success: complexityLevel !== 'very-high',
80
+ message: `${emoji} ${message}`,
81
+ warnings,
82
+ suggestions,
83
+ data: {
84
+ complexityScore,
85
+ complexityLevel,
86
+ metrics: {
87
+ requirementCount,
88
+ scenarioCount,
89
+ integrationPoints,
90
+ dependencies,
91
+ },
92
+ },
93
+ };
94
+ },
95
+ },
96
+ };
97
+ //# sourceMappingURL=complexity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"complexity.js","sourceRoot":"","sources":["../../../src/extensions/builtins/complexity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Extension } from '../types.js';
2
+ /**
3
+ * OWASP Security Extension
4
+ * Checks specs for security requirements and flags missing considerations
5
+ */
6
+ export declare const owaspExtension: Extension;
7
+ //# sourceMappingURL=owasp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owasp.d.ts","sourceRoot":"","sources":["../../../src/extensions/builtins/owasp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAqC,MAAM,aAAa,CAAC;AAEhF;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,SA6E5B,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * OWASP Security Extension
3
+ * Checks specs for security requirements and flags missing considerations
4
+ */
5
+ export const owaspExtension = {
6
+ id: 'owasp-security',
7
+ name: 'OWASP Security Checker',
8
+ description: 'Validates spec against OWASP security best practices',
9
+ version: '1.0.0',
10
+ author: 'SpecSafe Team',
11
+ enabled: true,
12
+ hooks: {
13
+ 'post-validate': (context) => {
14
+ const { spec } = context;
15
+ const warnings = [];
16
+ const suggestions = [];
17
+ const errors = [];
18
+ // Convert spec description and requirements to lowercase for checking
19
+ const descLower = (spec.description || '').toLowerCase();
20
+ const reqTexts = Array.isArray(spec.requirements)
21
+ ? spec.requirements.map(r => `${r.text || ''} ${(r.scenarios || []).map(s => s.when).join(' ')}`.toLowerCase())
22
+ : [];
23
+ const allText = [descLower, ...reqTexts].join(' ');
24
+ // Security keywords to check
25
+ const securityChecks = {
26
+ authentication: ['authentication', 'login', 'signin', 'auth'],
27
+ authorization: ['authorization', 'permission', 'access control', 'role'],
28
+ inputValidation: ['validation', 'sanitize', 'input', 'escape'],
29
+ encryption: ['encryption', 'encrypt', 'ssl', 'tls', 'https'],
30
+ dataProtection: ['data protection', 'privacy', 'gdpr', 'sensitive data'],
31
+ };
32
+ let foundCount = 0;
33
+ // Check for each security aspect
34
+ for (const [aspect, keywords] of Object.entries(securityChecks)) {
35
+ const found = keywords.some(keyword => allText.includes(keyword));
36
+ if (!found) {
37
+ warnings.push(`No mention of ${aspect} found`);
38
+ suggestions.push(`Consider adding ${aspect} requirements`);
39
+ }
40
+ else {
41
+ foundCount++;
42
+ }
43
+ }
44
+ // Determine result
45
+ const totalChecks = Object.keys(securityChecks).length;
46
+ const coverage = (foundCount / totalChecks) * 100;
47
+ let message = `Security coverage: ${foundCount}/${totalChecks} aspects (${Math.round(coverage)}%)`;
48
+ let success = true;
49
+ if (foundCount === 0) {
50
+ errors.push('No security considerations found in spec');
51
+ message = '⚠️ Critical: No security requirements detected';
52
+ success = false;
53
+ }
54
+ else if (foundCount < 3) {
55
+ warnings.push('Low security coverage detected');
56
+ message = `⚠️ Warning: ${message}`;
57
+ }
58
+ else {
59
+ message = `✓ ${message}`;
60
+ }
61
+ return {
62
+ success,
63
+ message,
64
+ warnings,
65
+ suggestions,
66
+ errors,
67
+ data: {
68
+ coverage,
69
+ foundCount,
70
+ totalChecks,
71
+ },
72
+ };
73
+ },
74
+ },
75
+ };
76
+ //# sourceMappingURL=owasp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owasp.js","sourceRoot":"","sources":["../../../src/extensions/builtins/owasp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * SpecSafe Extension System
3
+ *
4
+ * Provides a plugin architecture for extending SpecSafe functionality
5
+ * at various lifecycle hooks.
6
+ */
7
+ export type { Extension, ExtensionHook, ExtensionContext, ExtensionResult, HookRegistration, } from './types.js';
8
+ export { ExtensionRegistry } from './registry.js';
9
+ import type { Extension, ExtensionHook, ExtensionContext, ExtensionResult } from './types.js';
10
+ /**
11
+ * Register an extension
12
+ */
13
+ export declare function registerExtension(extension: Extension): void;
14
+ /**
15
+ * Unregister an extension
16
+ */
17
+ export declare function unregisterExtension(extensionId: string): boolean;
18
+ /**
19
+ * Get an extension by ID
20
+ */
21
+ export declare function getExtension(extensionId: string): Extension | undefined;
22
+ /**
23
+ * List all registered extensions
24
+ */
25
+ export declare function listExtensions(): Extension[];
26
+ /**
27
+ * List enabled extensions only
28
+ */
29
+ export declare function listEnabledExtensions(): Extension[];
30
+ /**
31
+ * Check if an extension exists
32
+ */
33
+ export declare function hasExtension(extensionId: string): boolean;
34
+ /**
35
+ * Enable an extension
36
+ */
37
+ export declare function enableExtension(extensionId: string): boolean;
38
+ /**
39
+ * Disable an extension
40
+ */
41
+ export declare function disableExtension(extensionId: string): boolean;
42
+ /**
43
+ * Execute hooks for a phase
44
+ */
45
+ export declare function executeHooks(phase: ExtensionHook, context: ExtensionContext): Promise<ExtensionResult[]>;
46
+ /**
47
+ * Clear all extensions (useful for testing)
48
+ */
49
+ export declare function clearExtensions(): void;
50
+ export { validateExtension, loadExtension, loadExtensions, loadBuiltinExtensions } from './loader.js';
51
+ export type { Extension as ExtensionConfig } from './types.js';
52
+ export type { ExtensionHook as ExtensionPhase } from './types.js';
53
+ export type ExtensionRegistryEntry = Extension;
54
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE9F;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAE5D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEvE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,SAAS,EAAE,CAE5C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,SAAS,EAAE,CAEnD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAExG;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAGD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAGtG,YAAY,EAAE,SAAS,IAAI,eAAe,EAAE,MAAM,YAAY,CAAC;AAC/D,YAAY,EAAE,aAAa,IAAI,cAAc,EAAE,MAAM,YAAY,CAAC;AAClE,MAAM,MAAM,sBAAsB,GAAG,SAAS,CAAC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * SpecSafe Extension System
3
+ *
4
+ * Provides a plugin architecture for extending SpecSafe functionality
5
+ * at various lifecycle hooks.
6
+ */
7
+ // Re-export registry methods as standalone functions
8
+ export { ExtensionRegistry } from './registry.js';
9
+ import { ExtensionRegistry } from './registry.js';
10
+ /**
11
+ * Register an extension
12
+ */
13
+ export function registerExtension(extension) {
14
+ ExtensionRegistry.register(extension);
15
+ }
16
+ /**
17
+ * Unregister an extension
18
+ */
19
+ export function unregisterExtension(extensionId) {
20
+ return ExtensionRegistry.unregister(extensionId);
21
+ }
22
+ /**
23
+ * Get an extension by ID
24
+ */
25
+ export function getExtension(extensionId) {
26
+ return ExtensionRegistry.get(extensionId);
27
+ }
28
+ /**
29
+ * List all registered extensions
30
+ */
31
+ export function listExtensions() {
32
+ return ExtensionRegistry.list();
33
+ }
34
+ /**
35
+ * List enabled extensions only
36
+ */
37
+ export function listEnabledExtensions() {
38
+ return ExtensionRegistry.listEnabled();
39
+ }
40
+ /**
41
+ * Check if an extension exists
42
+ */
43
+ export function hasExtension(extensionId) {
44
+ return ExtensionRegistry.has(extensionId);
45
+ }
46
+ /**
47
+ * Enable an extension
48
+ */
49
+ export function enableExtension(extensionId) {
50
+ return ExtensionRegistry.enable(extensionId);
51
+ }
52
+ /**
53
+ * Disable an extension
54
+ */
55
+ export function disableExtension(extensionId) {
56
+ return ExtensionRegistry.disable(extensionId);
57
+ }
58
+ /**
59
+ * Execute hooks for a phase
60
+ */
61
+ export function executeHooks(phase, context) {
62
+ return ExtensionRegistry.executeHooks(phase, context);
63
+ }
64
+ /**
65
+ * Clear all extensions (useful for testing)
66
+ */
67
+ export function clearExtensions() {
68
+ ExtensionRegistry.clear();
69
+ }
70
+ // Loader exports
71
+ export { validateExtension, loadExtension, loadExtensions, loadBuiltinExtensions } from './loader.js';
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,qDAAqD;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAoB;IACpD,iBAAiB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,OAAO,iBAAiB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,iBAAiB,CAAC,IAAI,EAAE,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,iBAAiB,CAAC,WAAW,EAAE,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,WAAmB;IACjD,OAAO,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,OAAO,iBAAiB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAoB,EAAE,OAAyB;IAC1E,OAAO,iBAAiB,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,iBAAiB,CAAC,KAAK,EAAE,CAAC;AAC5B,CAAC;AAED,iBAAiB;AACjB,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { Extension } from './types.js';
2
+ /**
3
+ * Validate extension structure
4
+ * @param ext - Extension to validate
5
+ * @returns true if extension is valid
6
+ * @throws Error if extension is invalid
7
+ */
8
+ export declare function validateExtension(ext: unknown): ext is Extension;
9
+ /**
10
+ * Load a single extension
11
+ * @param extension - Extension to load
12
+ * @param autoRegister - Whether to automatically register the extension (default: true)
13
+ * @returns The loaded extension
14
+ */
15
+ export declare function loadExtension(extension: Extension, autoRegister?: boolean): Extension;
16
+ /**
17
+ * Load multiple extensions
18
+ * @param extensions - Array of extensions to load
19
+ * @param autoRegister - Whether to automatically register extensions (default: true)
20
+ * @returns Array of loaded extensions
21
+ */
22
+ export declare function loadExtensions(extensions: Extension[], autoRegister?: boolean): Extension[];
23
+ /**
24
+ * Load builtin extensions
25
+ * @returns Array of loaded builtin extensions
26
+ */
27
+ export declare function loadBuiltinExtensions(): Promise<Extension[]>;
28
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/extensions/loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,SAAS,CA4BhE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,YAAY,UAAO,GAAG,SAAS,CAQlF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,SAAS,EAAE,EAAE,YAAY,UAAO,GAAG,SAAS,EAAE,CAExF;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAOlE"}
@@ -0,0 +1,62 @@
1
+ import { ExtensionRegistry } from './registry.js';
2
+ /**
3
+ * Validate extension structure
4
+ * @param ext - Extension to validate
5
+ * @returns true if extension is valid
6
+ * @throws Error if extension is invalid
7
+ */
8
+ export function validateExtension(ext) {
9
+ if (!ext || typeof ext !== 'object') {
10
+ throw new Error('Extension must be an object');
11
+ }
12
+ const extension = ext;
13
+ if (!extension.id || typeof extension.id !== 'string') {
14
+ throw new Error('Extension must have a string "id" field');
15
+ }
16
+ if (!extension.name || typeof extension.name !== 'string') {
17
+ throw new Error('Extension must have a string "name" field');
18
+ }
19
+ if (!extension.description || typeof extension.description !== 'string') {
20
+ throw new Error('Extension must have a string "description" field');
21
+ }
22
+ if (!extension.version || typeof extension.version !== 'string') {
23
+ throw new Error('Extension must have a string "version" field');
24
+ }
25
+ if (!extension.hooks || typeof extension.hooks !== 'object') {
26
+ throw new Error('Extension must have a "hooks" object');
27
+ }
28
+ return true;
29
+ }
30
+ /**
31
+ * Load a single extension
32
+ * @param extension - Extension to load
33
+ * @param autoRegister - Whether to automatically register the extension (default: true)
34
+ * @returns The loaded extension
35
+ */
36
+ export function loadExtension(extension, autoRegister = true) {
37
+ validateExtension(extension);
38
+ if (autoRegister) {
39
+ ExtensionRegistry.register(extension);
40
+ }
41
+ return extension;
42
+ }
43
+ /**
44
+ * Load multiple extensions
45
+ * @param extensions - Array of extensions to load
46
+ * @param autoRegister - Whether to automatically register extensions (default: true)
47
+ * @returns Array of loaded extensions
48
+ */
49
+ export function loadExtensions(extensions, autoRegister = true) {
50
+ return extensions.map(ext => loadExtension(ext, autoRegister));
51
+ }
52
+ /**
53
+ * Load builtin extensions
54
+ * @returns Array of loaded builtin extensions
55
+ */
56
+ export async function loadBuiltinExtensions() {
57
+ const { owaspExtension } = await import('./builtins/owasp.js');
58
+ const { complexityExtension } = await import('./builtins/complexity.js');
59
+ const builtins = [owaspExtension, complexityExtension];
60
+ return loadExtensions(builtins, true);
61
+ }
62
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/extensions/loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,SAAS,GAAG,GAAyB,CAAC;IAE5C,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,OAAO,SAAS,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,OAAO,SAAS,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,OAAO,SAAS,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,OAAO,SAAS,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,OAAO,SAAS,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,SAAoB,EAAE,YAAY,GAAG,IAAI;IACrE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAE7B,IAAI,YAAY,EAAE,CAAC;QACjB,iBAAiB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,UAAuB,EAAE,YAAY,GAAG,IAAI;IACzE,OAAO,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAC/D,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;IAEzE,MAAM,QAAQ,GAAG,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;IAEvD,OAAO,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,74 @@
1
+ import type { Extension, ExtensionHook, ExtensionContext, ExtensionResult, HookRegistration } from './types.js';
2
+ /**
3
+ * Global extension registry
4
+ */
5
+ declare class ExtensionRegistryClass {
6
+ private extensions;
7
+ private hooks;
8
+ /**
9
+ * Register an extension
10
+ * @param extension - Extension to register
11
+ * @throws Error if extension with same ID already exists
12
+ */
13
+ register(extension: Extension): void;
14
+ /**
15
+ * Unregister an extension
16
+ * @param extensionId - ID of extension to unregister
17
+ * @returns true if extension was found and removed
18
+ */
19
+ unregister(extensionId: string): boolean;
20
+ /**
21
+ * Get an extension by ID
22
+ * @param extensionId - Extension ID
23
+ * @returns Extension or undefined if not found
24
+ */
25
+ get(extensionId: string): Extension | undefined;
26
+ /**
27
+ * Get all registered extensions
28
+ * @returns Array of all extensions
29
+ */
30
+ list(): Extension[];
31
+ /**
32
+ * Get enabled extensions only
33
+ * @returns Array of enabled extensions
34
+ */
35
+ listEnabled(): Extension[];
36
+ /**
37
+ * Check if an extension exists
38
+ * @param extensionId - Extension ID
39
+ * @returns true if extension is registered
40
+ */
41
+ has(extensionId: string): boolean;
42
+ /**
43
+ * Enable an extension
44
+ * @param extensionId - Extension ID
45
+ * @returns true if extension was found and enabled
46
+ */
47
+ enable(extensionId: string): boolean;
48
+ /**
49
+ * Disable an extension
50
+ * @param extensionId - Extension ID
51
+ * @returns true if extension was found and disabled
52
+ */
53
+ disable(extensionId: string): boolean;
54
+ /**
55
+ * Get hooks for a specific phase
56
+ * @param phase - Hook phase
57
+ * @returns Array of hook registrations for this phase
58
+ */
59
+ getHooks(phase: ExtensionHook): HookRegistration[];
60
+ /**
61
+ * Execute all hooks for a phase
62
+ * @param phase - Hook phase
63
+ * @param context - Extension context
64
+ * @returns Array of results from all hooks
65
+ */
66
+ executeHooks(phase: ExtensionHook, context: ExtensionContext): Promise<ExtensionResult[]>;
67
+ /**
68
+ * Clear all extensions (useful for testing)
69
+ */
70
+ clear(): void;
71
+ }
72
+ export declare const ExtensionRegistry: ExtensionRegistryClass;
73
+ export {};
74
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/extensions/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhH;;GAEG;AACH,cAAM,sBAAsB;IAC1B,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,KAAK,CAAqD;IAElE;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAyBpC;;;;OAIG;IACH,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAoBxC;;;;OAIG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI/C;;;OAGG;IACH,IAAI,IAAI,SAAS,EAAE;IAInB;;;OAGG;IACH,WAAW,IAAI,SAAS,EAAE;IAI1B;;;;OAIG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIjC;;;;OAIG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IASpC;;;;OAIG;IACH,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IASrC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,gBAAgB,EAAE;IAIlD;;;;;OAKG;IACG,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA0B/F;;OAEG;IACH,KAAK,IAAI,IAAI;CAId;AAGD,eAAO,MAAM,iBAAiB,wBAA+B,CAAC"}