@planu/cli 0.96.4 → 0.97.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 (238) hide show
  1. package/dist/cli/commands/install.d.ts.map +1 -1
  2. package/dist/cli/commands/install.js +70 -2
  3. package/dist/cli/commands/install.js.map +1 -1
  4. package/dist/config/compliance-profiles.json +62 -0
  5. package/dist/config/license-plans.json +19 -2
  6. package/dist/config/spec-templates/crud-rest-api/spec.md +35 -0
  7. package/dist/config/spec-templates/crud-rest-api/template.json +10 -0
  8. package/dist/config/spec-templates/email-notifications/spec.md +31 -0
  9. package/dist/config/spec-templates/email-notifications/template.json +10 -0
  10. package/dist/config/spec-templates/file-upload-s3/spec.md +31 -0
  11. package/dist/config/spec-templates/file-upload-s3/template.json +11 -0
  12. package/dist/config/spec-templates/jwt-auth/spec.md +35 -0
  13. package/dist/config/spec-templates/jwt-auth/template.json +10 -0
  14. package/dist/config/spec-templates/oauth-social-login/spec.md +31 -0
  15. package/dist/config/spec-templates/oauth-social-login/template.json +10 -0
  16. package/dist/config/spec-templates/rate-limiting/spec.md +31 -0
  17. package/dist/config/spec-templates/rate-limiting/template.json +10 -0
  18. package/dist/config/spec-templates/stripe-payments/spec.md +32 -0
  19. package/dist/config/spec-templates/stripe-payments/template.json +10 -0
  20. package/dist/config/spec-templates/webhook-system/spec.md +36 -0
  21. package/dist/config/spec-templates/webhook-system/template.json +10 -0
  22. package/dist/engine/agent-ready-exporter/formatters/devin.d.ts +7 -0
  23. package/dist/engine/agent-ready-exporter/formatters/devin.d.ts.map +1 -0
  24. package/dist/engine/agent-ready-exporter/formatters/devin.js +23 -0
  25. package/dist/engine/agent-ready-exporter/formatters/devin.js.map +1 -0
  26. package/dist/engine/agent-ready-exporter/formatters/generic.d.ts +7 -0
  27. package/dist/engine/agent-ready-exporter/formatters/generic.d.ts.map +1 -0
  28. package/dist/engine/agent-ready-exporter/formatters/generic.js +9 -0
  29. package/dist/engine/agent-ready-exporter/formatters/generic.js.map +1 -0
  30. package/dist/engine/agent-ready-exporter/formatters/kiro.d.ts +6 -0
  31. package/dist/engine/agent-ready-exporter/formatters/kiro.d.ts.map +1 -0
  32. package/dist/engine/agent-ready-exporter/formatters/kiro.js +34 -0
  33. package/dist/engine/agent-ready-exporter/formatters/kiro.js.map +1 -0
  34. package/dist/engine/agent-ready-exporter/formatters/swe-agent.d.ts +6 -0
  35. package/dist/engine/agent-ready-exporter/formatters/swe-agent.d.ts.map +1 -0
  36. package/dist/engine/agent-ready-exporter/formatters/swe-agent.js +40 -0
  37. package/dist/engine/agent-ready-exporter/formatters/swe-agent.js.map +1 -0
  38. package/dist/engine/agent-ready-exporter.d.ts +11 -0
  39. package/dist/engine/agent-ready-exporter.d.ts.map +1 -0
  40. package/dist/engine/agent-ready-exporter.js +86 -0
  41. package/dist/engine/agent-ready-exporter.js.map +1 -0
  42. package/dist/engine/compliance-checker.d.ts +19 -0
  43. package/dist/engine/compliance-checker.d.ts.map +1 -0
  44. package/dist/engine/compliance-checker.js +145 -0
  45. package/dist/engine/compliance-checker.js.map +1 -0
  46. package/dist/engine/generate-tests/generators/property-based-generator.d.ts +12 -0
  47. package/dist/engine/generate-tests/generators/property-based-generator.d.ts.map +1 -0
  48. package/dist/engine/generate-tests/generators/property-based-generator.js +159 -0
  49. package/dist/engine/generate-tests/generators/property-based-generator.js.map +1 -0
  50. package/dist/engine/jira-exporter.d.ts +39 -0
  51. package/dist/engine/jira-exporter.d.ts.map +1 -0
  52. package/dist/engine/jira-exporter.js +190 -0
  53. package/dist/engine/jira-exporter.js.map +1 -0
  54. package/dist/engine/linear-exporter.d.ts +32 -0
  55. package/dist/engine/linear-exporter.d.ts.map +1 -0
  56. package/dist/engine/linear-exporter.js +184 -0
  57. package/dist/engine/linear-exporter.js.map +1 -0
  58. package/dist/engine/planu-config-writer.d.ts +13 -2
  59. package/dist/engine/planu-config-writer.d.ts.map +1 -1
  60. package/dist/engine/planu-config-writer.js +32 -1
  61. package/dist/engine/planu-config-writer.js.map +1 -1
  62. package/dist/engine/property-test-generator.d.ts +14 -0
  63. package/dist/engine/property-test-generator.d.ts.map +1 -0
  64. package/dist/engine/property-test-generator.js +223 -0
  65. package/dist/engine/property-test-generator.js.map +1 -0
  66. package/dist/engine/skill-evaluator.d.ts +21 -0
  67. package/dist/engine/skill-evaluator.d.ts.map +1 -0
  68. package/dist/engine/skill-evaluator.js +126 -0
  69. package/dist/engine/skill-evaluator.js.map +1 -0
  70. package/dist/engine/spec-quality-scorer.d.ts +4 -0
  71. package/dist/engine/spec-quality-scorer.d.ts.map +1 -0
  72. package/dist/engine/spec-quality-scorer.js +334 -0
  73. package/dist/engine/spec-quality-scorer.js.map +1 -0
  74. package/dist/engine/spec-template-engine.d.ts +26 -0
  75. package/dist/engine/spec-template-engine.d.ts.map +1 -0
  76. package/dist/engine/spec-template-engine.js +127 -0
  77. package/dist/engine/spec-template-engine.js.map +1 -0
  78. package/dist/index.js +10 -0
  79. package/dist/index.js.map +1 -1
  80. package/dist/storage/compliance-store.d.ts +11 -0
  81. package/dist/storage/compliance-store.d.ts.map +1 -0
  82. package/dist/storage/compliance-store.js +30 -0
  83. package/dist/storage/compliance-store.js.map +1 -0
  84. package/dist/storage/jira-store.d.ts +30 -0
  85. package/dist/storage/jira-store.d.ts.map +1 -0
  86. package/dist/storage/jira-store.js +84 -0
  87. package/dist/storage/jira-store.js.map +1 -0
  88. package/dist/storage/linear-store.d.ts +30 -0
  89. package/dist/storage/linear-store.d.ts.map +1 -0
  90. package/dist/storage/linear-store.js +84 -0
  91. package/dist/storage/linear-store.js.map +1 -0
  92. package/dist/tools/check-readiness.d.ts.map +1 -1
  93. package/dist/tools/check-readiness.js +8 -2
  94. package/dist/tools/check-readiness.js.map +1 -1
  95. package/dist/tools/compliance-handler.d.ts +6 -0
  96. package/dist/tools/compliance-handler.d.ts.map +1 -0
  97. package/dist/tools/compliance-handler.js +99 -0
  98. package/dist/tools/compliance-handler.js.map +1 -0
  99. package/dist/tools/eval-skill-handler.d.ts +4 -0
  100. package/dist/tools/eval-skill-handler.d.ts.map +1 -0
  101. package/dist/tools/eval-skill-handler.js +26 -0
  102. package/dist/tools/eval-skill-handler.js.map +1 -0
  103. package/dist/tools/export-spec.d.ts.map +1 -1
  104. package/dist/tools/export-spec.js +42 -1
  105. package/dist/tools/export-spec.js.map +1 -1
  106. package/dist/tools/generate-tests/generators/property-based-generator.d.ts +11 -0
  107. package/dist/tools/generate-tests/generators/property-based-generator.d.ts.map +1 -0
  108. package/dist/tools/generate-tests/generators/property-based-generator.js +27 -0
  109. package/dist/tools/generate-tests/generators/property-based-generator.js.map +1 -0
  110. package/dist/tools/generate-tests/spec-dispatcher.d.ts +5 -0
  111. package/dist/tools/generate-tests/spec-dispatcher.d.ts.map +1 -1
  112. package/dist/tools/generate-tests/spec-dispatcher.js +18 -1
  113. package/dist/tools/generate-tests/spec-dispatcher.js.map +1 -1
  114. package/dist/tools/init-project/config-builder.d.ts +3 -2
  115. package/dist/tools/init-project/config-builder.d.ts.map +1 -1
  116. package/dist/tools/init-project/config-builder.js +9 -4
  117. package/dist/tools/init-project/config-builder.js.map +1 -1
  118. package/dist/tools/init-project/handler.d.ts.map +1 -1
  119. package/dist/tools/init-project/handler.js +3 -2
  120. package/dist/tools/init-project/handler.js.map +1 -1
  121. package/dist/tools/jira-sync-handler.d.ts +6 -0
  122. package/dist/tools/jira-sync-handler.d.ts.map +1 -0
  123. package/dist/tools/jira-sync-handler.js +220 -0
  124. package/dist/tools/jira-sync-handler.js.map +1 -0
  125. package/dist/tools/linear-sync-handler.d.ts +6 -0
  126. package/dist/tools/linear-sync-handler.d.ts.map +1 -0
  127. package/dist/tools/linear-sync-handler.js +212 -0
  128. package/dist/tools/linear-sync-handler.js.map +1 -0
  129. package/dist/tools/register-export-tools.d.ts.map +1 -1
  130. package/dist/tools/register-export-tools.js +10 -3
  131. package/dist/tools/register-export-tools.js.map +1 -1
  132. package/dist/tools/register-spec-314.d.ts +3 -0
  133. package/dist/tools/register-spec-314.d.ts.map +1 -0
  134. package/dist/tools/register-spec-314.js +38 -0
  135. package/dist/tools/register-spec-314.js.map +1 -0
  136. package/dist/tools/register-spec-316.d.ts +3 -0
  137. package/dist/tools/register-spec-316.d.ts.map +1 -0
  138. package/dist/tools/register-spec-316.js +71 -0
  139. package/dist/tools/register-spec-316.js.map +1 -0
  140. package/dist/tools/register-spec-317.d.ts +3 -0
  141. package/dist/tools/register-spec-317.d.ts.map +1 -0
  142. package/dist/tools/register-spec-317.js +158 -0
  143. package/dist/tools/register-spec-317.js.map +1 -0
  144. package/dist/tools/register-spec-319.d.ts +3 -0
  145. package/dist/tools/register-spec-319.d.ts.map +1 -0
  146. package/dist/tools/register-spec-319.js +59 -0
  147. package/dist/tools/register-spec-319.js.map +1 -0
  148. package/dist/tools/register-spec-320.d.ts +3 -0
  149. package/dist/tools/register-spec-320.d.ts.map +1 -0
  150. package/dist/tools/register-spec-320.js +60 -0
  151. package/dist/tools/register-spec-320.js.map +1 -0
  152. package/dist/tools/register-spec-tools/core-spec-tools.d.ts.map +1 -1
  153. package/dist/tools/register-spec-tools/core-spec-tools.js +15 -1
  154. package/dist/tools/register-spec-tools/core-spec-tools.js.map +1 -1
  155. package/dist/tools/schemas/index.d.ts +1 -1
  156. package/dist/tools/schemas/index.d.ts.map +1 -1
  157. package/dist/tools/schemas/index.js +1 -1
  158. package/dist/tools/schemas/index.js.map +1 -1
  159. package/dist/tools/schemas/spec.d.ts +6 -0
  160. package/dist/tools/schemas/spec.d.ts.map +1 -1
  161. package/dist/tools/schemas/spec.js +4 -0
  162. package/dist/tools/schemas/spec.js.map +1 -1
  163. package/dist/tools/set-work-mode-handler.d.ts +7 -0
  164. package/dist/tools/set-work-mode-handler.d.ts.map +1 -0
  165. package/dist/tools/set-work-mode-handler.js +30 -0
  166. package/dist/tools/set-work-mode-handler.js.map +1 -0
  167. package/dist/tools/spec-marketplace-handler.d.ts +6 -0
  168. package/dist/tools/spec-marketplace-handler.d.ts.map +1 -0
  169. package/dist/tools/spec-marketplace-handler.js +113 -0
  170. package/dist/tools/spec-marketplace-handler.js.map +1 -0
  171. package/dist/tools/spec-quality-score-handler.d.ts +7 -0
  172. package/dist/tools/spec-quality-score-handler.d.ts.map +1 -0
  173. package/dist/tools/spec-quality-score-handler.js +106 -0
  174. package/dist/tools/spec-quality-score-handler.js.map +1 -0
  175. package/dist/tools/status-handler.d.ts.map +1 -1
  176. package/dist/tools/status-handler.js +12 -3
  177. package/dist/tools/status-handler.js.map +1 -1
  178. package/dist/types/agent-ready.d.ts +58 -0
  179. package/dist/types/agent-ready.d.ts.map +1 -0
  180. package/dist/types/agent-ready.js +3 -0
  181. package/dist/types/agent-ready.js.map +1 -0
  182. package/dist/types/common/primitives.d.ts +2 -0
  183. package/dist/types/common/primitives.d.ts.map +1 -1
  184. package/dist/types/compliance.d.ts +44 -0
  185. package/dist/types/compliance.d.ts.map +1 -0
  186. package/dist/types/compliance.js +3 -0
  187. package/dist/types/compliance.js.map +1 -0
  188. package/dist/types/export.d.ts +5 -1
  189. package/dist/types/export.d.ts.map +1 -1
  190. package/dist/types/export.js +1 -1
  191. package/dist/types/export.js.map +1 -1
  192. package/dist/types/index.d.ts +7 -0
  193. package/dist/types/index.d.ts.map +1 -1
  194. package/dist/types/index.js +7 -0
  195. package/dist/types/index.js.map +1 -1
  196. package/dist/types/jira-linear.d.ts +216 -0
  197. package/dist/types/jira-linear.d.ts.map +1 -0
  198. package/dist/types/jira-linear.js +3 -0
  199. package/dist/types/jira-linear.js.map +1 -0
  200. package/dist/types/project/inputs.d.ts +3 -1
  201. package/dist/types/project/inputs.d.ts.map +1 -1
  202. package/dist/types/project/planu-config.d.ts +2 -0
  203. package/dist/types/project/planu-config.d.ts.map +1 -1
  204. package/dist/types/property-testing.d.ts +50 -0
  205. package/dist/types/property-testing.d.ts.map +1 -0
  206. package/dist/types/property-testing.js +3 -0
  207. package/dist/types/property-testing.js.map +1 -0
  208. package/dist/types/skill-eval.d.ts +41 -0
  209. package/dist/types/skill-eval.d.ts.map +1 -0
  210. package/dist/types/skill-eval.js +3 -0
  211. package/dist/types/skill-eval.js.map +1 -0
  212. package/dist/types/spec-marketplace.d.ts +31 -0
  213. package/dist/types/spec-marketplace.d.ts.map +1 -0
  214. package/dist/types/spec-marketplace.js +3 -0
  215. package/dist/types/spec-marketplace.js.map +1 -0
  216. package/dist/types/spec-quality.d.ts +36 -0
  217. package/dist/types/spec-quality.d.ts.map +1 -0
  218. package/dist/types/spec-quality.js +3 -0
  219. package/dist/types/spec-quality.js.map +1 -0
  220. package/package.json +7 -2
  221. package/src/config/compliance-profiles.json +62 -0
  222. package/src/config/license-plans.json +19 -2
  223. package/src/config/spec-templates/crud-rest-api/spec.md +35 -0
  224. package/src/config/spec-templates/crud-rest-api/template.json +10 -0
  225. package/src/config/spec-templates/email-notifications/spec.md +31 -0
  226. package/src/config/spec-templates/email-notifications/template.json +10 -0
  227. package/src/config/spec-templates/file-upload-s3/spec.md +31 -0
  228. package/src/config/spec-templates/file-upload-s3/template.json +11 -0
  229. package/src/config/spec-templates/jwt-auth/spec.md +35 -0
  230. package/src/config/spec-templates/jwt-auth/template.json +10 -0
  231. package/src/config/spec-templates/oauth-social-login/spec.md +31 -0
  232. package/src/config/spec-templates/oauth-social-login/template.json +10 -0
  233. package/src/config/spec-templates/rate-limiting/spec.md +31 -0
  234. package/src/config/spec-templates/rate-limiting/template.json +10 -0
  235. package/src/config/spec-templates/stripe-payments/spec.md +32 -0
  236. package/src/config/spec-templates/stripe-payments/template.json +10 -0
  237. package/src/config/spec-templates/webhook-system/spec.md +36 -0
  238. package/src/config/spec-templates/webhook-system/template.json +10 -0
@@ -0,0 +1,159 @@
1
+ // engine/generate-tests/generators/property-based-generator.ts — SPEC-315
2
+ // High-level generator: produces a full test file string from spec + context.
3
+ import { extractPropertyTests, detectPropertyFramework } from '../../property-test-generator.js';
4
+ // ---------------------------------------------------------------------------
5
+ // File header builders per framework
6
+ // ---------------------------------------------------------------------------
7
+ function buildFastCheckHeader(specTitle) {
8
+ return `// Property-based tests for: ${specTitle}
9
+ // Generated by Planu SDD — strategy:property-based (SPEC-315)
10
+ // Framework: fast-check
11
+
12
+ import * as fc from 'fast-check';
13
+ import { describe, it } from 'vitest';
14
+
15
+ describe('${specTitle} — property-based tests', () => {`;
16
+ }
17
+ function buildHypothesisHeader(specTitle) {
18
+ return `# Property-based tests for: ${specTitle}
19
+ # Generated by Planu SDD — strategy:property-based (SPEC-315)
20
+ # Framework: hypothesis
21
+
22
+ from hypothesis import given, settings, HealthCheck
23
+ from hypothesis import strategies as st
24
+
25
+
26
+ class Test${specTitle.replace(/[^a-zA-Z0-9]/g, '')}Properties:
27
+ """Property-based tests for ${specTitle}."""
28
+ `;
29
+ }
30
+ function buildJqwikHeader(specTitle) {
31
+ const className = specTitle.replace(/[^a-zA-Z0-9]/g, '');
32
+ return `// Property-based tests for: ${specTitle}
33
+ // Generated by Planu SDD — strategy:property-based (SPEC-315)
34
+ // Framework: jqwik
35
+
36
+ import net.jqwik.api.*;
37
+ import static org.assertj.core.api.Assertions.assertThat;
38
+
39
+ class ${className}PropertyTest {`;
40
+ }
41
+ function buildGenericHeader(specTitle) {
42
+ return `# Property-based tests for: ${specTitle}
43
+ # Generated by Planu SDD — strategy:property-based (SPEC-315)
44
+ # Framework: generic (adapt to your property testing library)
45
+ #
46
+ # Each property below describes an invariant that must hold for ALL valid inputs.
47
+ # Implement using your project's property testing framework.
48
+ `;
49
+ }
50
+ // ---------------------------------------------------------------------------
51
+ // Test block builders per framework
52
+ // ---------------------------------------------------------------------------
53
+ function buildFastCheckBlock(test, index) {
54
+ return `
55
+ it('property ${index + 1}: ${test.invariant}', () => {
56
+ // Input domain: ${test.inputDomain}
57
+ // Shrink: ${test.shrinkStrategy}
58
+ ${test.generatorCode}
59
+ });`;
60
+ }
61
+ function buildHypothesisBlock(test, _index) {
62
+ return `
63
+ ${test.generatorCode}
64
+ `;
65
+ }
66
+ function buildJqwikBlock(test, _index) {
67
+ return `
68
+ // Input domain: ${test.inputDomain}
69
+ // Shrink: ${test.shrinkStrategy}
70
+ ${test.generatorCode}
71
+ `;
72
+ }
73
+ function buildGenericBlock(test, index) {
74
+ return `
75
+ # Property ${index + 1}
76
+ ${test.generatorCode}
77
+ `;
78
+ }
79
+ // ---------------------------------------------------------------------------
80
+ // File footer builders
81
+ // ---------------------------------------------------------------------------
82
+ function buildFastCheckFooter() {
83
+ return '\n});\n';
84
+ }
85
+ function buildJqwikFooter() {
86
+ return '\n}\n';
87
+ }
88
+ function buildNoFooter() {
89
+ return '\n';
90
+ }
91
+ // ---------------------------------------------------------------------------
92
+ // No-properties fallback
93
+ // ---------------------------------------------------------------------------
94
+ function buildFallbackContent(specTitle, language) {
95
+ if (language === 'python') {
96
+ return `# Property-based tests for: ${specTitle}
97
+ # Generated by Planu SDD — strategy:property-based (SPEC-315)
98
+ # No invariants detected in acceptance criteria.
99
+ # Add criteria with keywords: "must be positive", "idempotent", "for any input", etc.
100
+ `;
101
+ }
102
+ return `// Property-based tests for: ${specTitle}
103
+ // Generated by Planu SDD — strategy:property-based (SPEC-315)
104
+ // No invariants detected in acceptance criteria.
105
+ // Add criteria with keywords: "must be positive", "idempotent", "for any input", etc.
106
+ `;
107
+ }
108
+ // ---------------------------------------------------------------------------
109
+ // Public API
110
+ // ---------------------------------------------------------------------------
111
+ /**
112
+ * Generate a complete property-based test file as a string.
113
+ * Adapts output to fast-check (JS/TS), hypothesis (Python), jqwik (Java/Kotlin),
114
+ * or pseudo-code generic format based on detected framework.
115
+ *
116
+ * @param spec - The spec metadata (title, id used for file naming/headers).
117
+ * @param context - Project knowledge (language, stack) for framework detection.
118
+ * @param criteria - Acceptance criteria strings extracted from spec.md by the caller.
119
+ */
120
+ export function generatePropertyBasedTests(spec, context, criteria = []) {
121
+ const framework = detectPropertyFramework(context.language, context.stack);
122
+ const tests = extractPropertyTests({
123
+ criteria,
124
+ language: context.language,
125
+ stack: context.stack,
126
+ });
127
+ if (tests.length === 0) {
128
+ return buildFallbackContent(spec.title, context.language);
129
+ }
130
+ // Build header
131
+ let header;
132
+ let blockBuilder;
133
+ let footer;
134
+ switch (framework) {
135
+ case 'fast-check':
136
+ header = buildFastCheckHeader(spec.title);
137
+ blockBuilder = buildFastCheckBlock;
138
+ footer = buildFastCheckFooter();
139
+ break;
140
+ case 'hypothesis':
141
+ header = buildHypothesisHeader(spec.title);
142
+ blockBuilder = buildHypothesisBlock;
143
+ footer = buildNoFooter();
144
+ break;
145
+ case 'jqwik':
146
+ header = buildJqwikHeader(spec.title);
147
+ blockBuilder = buildJqwikBlock;
148
+ footer = buildJqwikFooter();
149
+ break;
150
+ case 'generic':
151
+ header = buildGenericHeader(spec.title);
152
+ blockBuilder = buildGenericBlock;
153
+ footer = buildNoFooter();
154
+ break;
155
+ }
156
+ const blocks = tests.map((test, i) => blockBuilder(test, i)).join('');
157
+ return `${header}${blocks}${footer}`;
158
+ }
159
+ //# sourceMappingURL=property-based-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-based-generator.js","sourceRoot":"","sources":["../../../../src/engine/generate-tests/generators/property-based-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { JiraConfig, JiraIssueRef, JiraApiIssue, Spec } from '../types/index.js';
2
+ /**
3
+ * Map a Planu spec status to a Jira status name.
4
+ */
5
+ export declare function mapSpecStatusToJira(specStatus: string): string;
6
+ export declare class JiraClient {
7
+ private readonly config;
8
+ private readonly authHeader;
9
+ private readonly baseUrl;
10
+ constructor(config: JiraConfig);
11
+ /**
12
+ * Create an Epic in Jira from a spec.
13
+ * Returns a JiraIssueRef with the new issue details.
14
+ */
15
+ createEpic(spec: Spec): Promise<JiraIssueRef>;
16
+ /**
17
+ * Create a Story in Jira linked to a parent Epic.
18
+ * Returns a JiraIssueRef for the created story.
19
+ */
20
+ createStory(specId: string, criterionText: string, epicKey: string): Promise<JiraIssueRef>;
21
+ /**
22
+ * Fetch a Jira issue by key.
23
+ * Returns the issue or null if not found.
24
+ */
25
+ getIssue(key: string): Promise<JiraApiIssue | null>;
26
+ /**
27
+ * Transition a Jira issue to a target status name.
28
+ * Looks up available transitions and applies the matching one.
29
+ */
30
+ updateIssueStatus(issueKey: string, targetStatus: string): Promise<void>;
31
+ private getTransitions;
32
+ private postJson;
33
+ }
34
+ /**
35
+ * Build a minimal Atlassian Document Format (ADF) document.
36
+ * Used for Jira issue descriptions in the REST API v3.
37
+ */
38
+ export declare function buildAtlassianDoc(heading: string, bodyText: string): Record<string, unknown>;
39
+ //# sourceMappingURL=jira-exporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jira-exporter.d.ts","sourceRoot":"","sources":["../../src/engine/jira-exporter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,UAAU,EACV,YAAY,EACZ,YAAY,EAEZ,IAAI,EACL,MAAM,mBAAmB,CAAC;AAc3B;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9D;AAMD,qBAAa,UAAU;IAIT,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAEJ,MAAM,EAAE,UAAU;IAM/C;;;OAGG;IACG,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;IA0BnD;;;OAGG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IA2BhG;;;OAGG;IACG,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAqBzD;;;OAGG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAgChE,cAAc;YAkBd,QAAQ;CAmBvB;AAMD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgBzB"}
@@ -0,0 +1,190 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Status mapping: Planu spec status → Jira issue status name
3
+ // ---------------------------------------------------------------------------
4
+ const SPEC_STATUS_TO_JIRA = {
5
+ draft: 'To Do',
6
+ review: 'In Review',
7
+ approved: 'Approved',
8
+ implementing: 'In Progress',
9
+ done: 'Done',
10
+ };
11
+ /**
12
+ * Map a Planu spec status to a Jira status name.
13
+ */
14
+ export function mapSpecStatusToJira(specStatus) {
15
+ return SPEC_STATUS_TO_JIRA[specStatus] ?? 'To Do';
16
+ }
17
+ // ---------------------------------------------------------------------------
18
+ // Jira REST API client
19
+ // ---------------------------------------------------------------------------
20
+ export class JiraClient {
21
+ config;
22
+ authHeader;
23
+ baseUrl;
24
+ constructor(config) {
25
+ this.config = config;
26
+ const credentials = `${config.email}:${config.apiToken}`;
27
+ this.authHeader = `Basic ${Buffer.from(credentials).toString('base64')}`;
28
+ this.baseUrl = `https://${config.domain}.atlassian.net/rest/api/3`;
29
+ }
30
+ /**
31
+ * Create an Epic in Jira from a spec.
32
+ * Returns a JiraIssueRef with the new issue details.
33
+ */
34
+ async createEpic(spec) {
35
+ const summary = `${spec.id}: ${spec.title}`;
36
+ const description = buildAtlassianDoc(spec.title, `Planu spec ${spec.id} — status: ${spec.status}`);
37
+ const payload = {
38
+ fields: {
39
+ project: { key: this.config.projectKey },
40
+ issuetype: { name: 'Epic' },
41
+ summary,
42
+ description,
43
+ labels: ['planu-spec'],
44
+ },
45
+ };
46
+ const data = await this.postJson('/issue', payload);
47
+ const issueUrl = `https://${this.config.domain}.atlassian.net/browse/${data.key}`;
48
+ return {
49
+ specId: spec.id,
50
+ issueKey: data.key,
51
+ issueUrl,
52
+ summary,
53
+ issueType: 'Epic',
54
+ };
55
+ }
56
+ /**
57
+ * Create a Story in Jira linked to a parent Epic.
58
+ * Returns a JiraIssueRef for the created story.
59
+ */
60
+ async createStory(specId, criterionText, epicKey) {
61
+ const summary = criterionText.slice(0, 255);
62
+ const description = buildAtlassianDoc('Acceptance Criterion', criterionText);
63
+ const payload = {
64
+ fields: {
65
+ project: { key: this.config.projectKey },
66
+ issuetype: { name: 'Story' },
67
+ summary,
68
+ description,
69
+ labels: ['planu-spec'],
70
+ 'Epic Link': epicKey,
71
+ },
72
+ };
73
+ const data = await this.postJson('/issue', payload);
74
+ const issueUrl = `https://${this.config.domain}.atlassian.net/browse/${data.key}`;
75
+ return {
76
+ specId,
77
+ issueKey: data.key,
78
+ issueUrl,
79
+ summary,
80
+ issueType: 'Story',
81
+ };
82
+ }
83
+ /**
84
+ * Fetch a Jira issue by key.
85
+ * Returns the issue or null if not found.
86
+ */
87
+ async getIssue(key) {
88
+ const url = `${this.baseUrl}/issue/${encodeURIComponent(key)}`;
89
+ const response = await globalThis.fetch(url, {
90
+ headers: {
91
+ Authorization: this.authHeader,
92
+ 'Content-Type': 'application/json',
93
+ },
94
+ signal: AbortSignal.timeout(10_000),
95
+ });
96
+ if (response.status === 404) {
97
+ return null;
98
+ }
99
+ if (!response.ok) {
100
+ throw new Error(`Jira getIssue failed: ${response.status} ${response.statusText}`);
101
+ }
102
+ return (await response.json());
103
+ }
104
+ /**
105
+ * Transition a Jira issue to a target status name.
106
+ * Looks up available transitions and applies the matching one.
107
+ */
108
+ async updateIssueStatus(issueKey, targetStatus) {
109
+ const transitions = await this.getTransitions(issueKey);
110
+ const match = transitions.find((t) => t.name.toLowerCase() === targetStatus.toLowerCase());
111
+ if (match === undefined) {
112
+ // Status not available — skip silently (workflow may differ per project)
113
+ return;
114
+ }
115
+ const url = `${this.baseUrl}/issue/${encodeURIComponent(issueKey)}/transitions`;
116
+ const response = await globalThis.fetch(url, {
117
+ method: 'POST',
118
+ headers: {
119
+ Authorization: this.authHeader,
120
+ 'Content-Type': 'application/json',
121
+ },
122
+ body: JSON.stringify({ transition: { id: match.id } }),
123
+ signal: AbortSignal.timeout(10_000),
124
+ });
125
+ if (!response.ok) {
126
+ const errText = await response.text();
127
+ throw new Error(`Jira updateIssueStatus failed: ${response.status} — ${errText}`);
128
+ }
129
+ }
130
+ // ---------------------------------------------------------------------------
131
+ // Private helpers
132
+ // ---------------------------------------------------------------------------
133
+ async getTransitions(issueKey) {
134
+ const url = `${this.baseUrl}/issue/${encodeURIComponent(issueKey)}/transitions`;
135
+ const response = await globalThis.fetch(url, {
136
+ headers: {
137
+ Authorization: this.authHeader,
138
+ 'Content-Type': 'application/json',
139
+ },
140
+ signal: AbortSignal.timeout(10_000),
141
+ });
142
+ if (!response.ok) {
143
+ return [];
144
+ }
145
+ const data = (await response.json());
146
+ return data.transitions;
147
+ }
148
+ async postJson(path, body) {
149
+ const url = `${this.baseUrl}${path}`;
150
+ const response = await globalThis.fetch(url, {
151
+ method: 'POST',
152
+ headers: {
153
+ Authorization: this.authHeader,
154
+ 'Content-Type': 'application/json',
155
+ },
156
+ body: JSON.stringify(body),
157
+ signal: AbortSignal.timeout(15_000),
158
+ });
159
+ if (!response.ok) {
160
+ const errText = await response.text();
161
+ throw new Error(`Jira POST ${path} failed: ${response.status} — ${errText}`);
162
+ }
163
+ return (await response.json());
164
+ }
165
+ }
166
+ // ---------------------------------------------------------------------------
167
+ // Atlassian Document Format (ADF) builder
168
+ // ---------------------------------------------------------------------------
169
+ /**
170
+ * Build a minimal Atlassian Document Format (ADF) document.
171
+ * Used for Jira issue descriptions in the REST API v3.
172
+ */
173
+ export function buildAtlassianDoc(heading, bodyText) {
174
+ return {
175
+ version: 1,
176
+ type: 'doc',
177
+ content: [
178
+ {
179
+ type: 'heading',
180
+ attrs: { level: 2 },
181
+ content: [{ type: 'text', text: heading }],
182
+ },
183
+ {
184
+ type: 'paragraph',
185
+ content: [{ type: 'text', text: bodyText }],
186
+ },
187
+ ],
188
+ };
189
+ }
190
+ //# sourceMappingURL=jira-exporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jira-exporter.js","sourceRoot":"","sources":["../../src/engine/jira-exporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { LinearConfig, LinearIssueRef, Spec } from '../types/index.js';
2
+ /**
3
+ * Map a Planu spec status to a Linear workflow state name.
4
+ */
5
+ export declare function mapSpecStatusToLinear(specStatus: string): string;
6
+ export declare class LinearClient {
7
+ private readonly config;
8
+ constructor(config: LinearConfig);
9
+ /**
10
+ * Create a Linear project (as an issue group / label) from a spec.
11
+ * Since Linear uses issues as primary entities, each spec becomes an issue.
12
+ * Returns a LinearIssueRef with the created issue details.
13
+ */
14
+ createProject(spec: Spec): Promise<LinearIssueRef>;
15
+ /**
16
+ * Create a sub-issue in Linear for a single acceptance criterion.
17
+ * Returns a LinearIssueRef for the created issue.
18
+ */
19
+ createIssue(specId: string, criterionText: string, parentId?: string): Promise<LinearIssueRef>;
20
+ /**
21
+ * Update the workflow state (status) of a Linear issue.
22
+ * Looks up the state ID by name within the team, then applies it.
23
+ */
24
+ updateIssueStatus(issueId: string, stateName: string): Promise<void>;
25
+ private findStateId;
26
+ private graphql;
27
+ }
28
+ /**
29
+ * Build a Markdown description for a Linear issue from a spec.
30
+ */
31
+ export declare function buildLinearDescription(spec: Spec): string;
32
+ //# sourceMappingURL=linear-exporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-exporter.d.ts","sourceRoot":"","sources":["../../src/engine/linear-exporter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EAId,IAAI,EACL,MAAM,mBAAmB,CAAC;AAgB3B;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEhE;AAMD,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,YAAY;IAEjD;;;;OAIG;IACG,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC;IAqCxD;;;OAGG;IACG,WAAW,CACf,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC;IAsC1B;;;OAGG;IACG,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YA6B5D,WAAW;YAuBX,OAAO;CA6BtB;AAMD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CASzD"}
@@ -0,0 +1,184 @@
1
+ const LINEAR_GRAPHQL_URL = 'https://api.linear.app/graphql';
2
+ // ---------------------------------------------------------------------------
3
+ // Status mapping: Planu spec status → Linear workflow state name
4
+ // ---------------------------------------------------------------------------
5
+ const SPEC_STATUS_TO_LINEAR = {
6
+ draft: 'Todo',
7
+ review: 'In Review',
8
+ approved: 'Todo',
9
+ implementing: 'In Progress',
10
+ done: 'Done',
11
+ };
12
+ /**
13
+ * Map a Planu spec status to a Linear workflow state name.
14
+ */
15
+ export function mapSpecStatusToLinear(specStatus) {
16
+ return SPEC_STATUS_TO_LINEAR[specStatus] ?? 'Todo';
17
+ }
18
+ // ---------------------------------------------------------------------------
19
+ // Linear GraphQL client
20
+ // ---------------------------------------------------------------------------
21
+ export class LinearClient {
22
+ config;
23
+ constructor(config) {
24
+ this.config = config;
25
+ }
26
+ /**
27
+ * Create a Linear project (as an issue group / label) from a spec.
28
+ * Since Linear uses issues as primary entities, each spec becomes an issue.
29
+ * Returns a LinearIssueRef with the created issue details.
30
+ */
31
+ async createProject(spec) {
32
+ const title = `${spec.id}: ${spec.title}`;
33
+ const description = buildLinearDescription(spec);
34
+ const mutation = `
35
+ mutation CreateIssue($input: IssueCreateInput!) {
36
+ issueCreate(input: $input) {
37
+ success
38
+ issue {
39
+ id
40
+ url
41
+ title
42
+ }
43
+ }
44
+ }
45
+ `;
46
+ const variables = {
47
+ input: {
48
+ teamId: this.config.teamId,
49
+ title,
50
+ description,
51
+ labelNames: ['planu-spec'],
52
+ },
53
+ };
54
+ const data = await this.graphql(mutation, variables);
55
+ const issue = data.issueCreate.issue;
56
+ return {
57
+ specId: spec.id,
58
+ issueId: issue.id,
59
+ issueUrl: issue.url,
60
+ title: issue.title,
61
+ };
62
+ }
63
+ /**
64
+ * Create a sub-issue in Linear for a single acceptance criterion.
65
+ * Returns a LinearIssueRef for the created issue.
66
+ */
67
+ async createIssue(specId, criterionText, parentId) {
68
+ const title = criterionText.slice(0, 255);
69
+ const mutation = `
70
+ mutation CreateIssue($input: IssueCreateInput!) {
71
+ issueCreate(input: $input) {
72
+ success
73
+ issue {
74
+ id
75
+ url
76
+ title
77
+ }
78
+ }
79
+ }
80
+ `;
81
+ const input = {
82
+ teamId: this.config.teamId,
83
+ title,
84
+ description: criterionText,
85
+ labelNames: ['planu-spec'],
86
+ };
87
+ if (parentId !== undefined) {
88
+ input.parentId = parentId;
89
+ }
90
+ const data = await this.graphql(mutation, { input });
91
+ const issue = data.issueCreate.issue;
92
+ return {
93
+ specId,
94
+ issueId: issue.id,
95
+ issueUrl: issue.url,
96
+ title: issue.title,
97
+ };
98
+ }
99
+ /**
100
+ * Update the workflow state (status) of a Linear issue.
101
+ * Looks up the state ID by name within the team, then applies it.
102
+ */
103
+ async updateIssueStatus(issueId, stateName) {
104
+ const stateId = await this.findStateId(stateName);
105
+ if (stateId === null) {
106
+ // State not found — skip silently
107
+ return;
108
+ }
109
+ const mutation = `
110
+ mutation UpdateIssue($id: String!, $input: IssueUpdateInput!) {
111
+ issueUpdate(id: $id, input: $input) {
112
+ success
113
+ }
114
+ }
115
+ `;
116
+ const data = await this.graphql(mutation, {
117
+ id: issueId,
118
+ input: { stateId },
119
+ });
120
+ if (!data.issueUpdate.success) {
121
+ throw new Error(`Linear updateIssueStatus failed for issue ${issueId}`);
122
+ }
123
+ }
124
+ // ---------------------------------------------------------------------------
125
+ // Private helpers
126
+ // ---------------------------------------------------------------------------
127
+ async findStateId(stateName) {
128
+ const query = `
129
+ query WorkflowStates($teamId: String!) {
130
+ workflowStates(filter: { team: { id: { eq: $teamId } } }) {
131
+ nodes {
132
+ id
133
+ name
134
+ }
135
+ }
136
+ }
137
+ `;
138
+ const data = await this.graphql(query, {
139
+ teamId: this.config.teamId,
140
+ });
141
+ const match = data.workflowStates.nodes.find((s) => s.name.toLowerCase() === stateName.toLowerCase());
142
+ return match?.id ?? null;
143
+ }
144
+ async graphql(query, variables) {
145
+ const response = await globalThis.fetch(LINEAR_GRAPHQL_URL, {
146
+ method: 'POST',
147
+ headers: {
148
+ Authorization: `Bearer ${this.config.apiKey}`,
149
+ 'Content-Type': 'application/json',
150
+ },
151
+ body: JSON.stringify({ query, variables }),
152
+ signal: AbortSignal.timeout(15_000),
153
+ });
154
+ if (!response.ok) {
155
+ const errText = await response.text();
156
+ throw new Error(`Linear GraphQL request failed: ${response.status} — ${errText}`);
157
+ }
158
+ const json = (await response.json());
159
+ if (json.errors !== undefined && json.errors.length > 0) {
160
+ const messages = json.errors.map((e) => e.message).join('; ');
161
+ throw new Error(`Linear GraphQL errors: ${messages}`);
162
+ }
163
+ if (json.data === undefined) {
164
+ throw new Error('Linear GraphQL returned no data');
165
+ }
166
+ return json.data;
167
+ }
168
+ }
169
+ // ---------------------------------------------------------------------------
170
+ // Description builder
171
+ // ---------------------------------------------------------------------------
172
+ /**
173
+ * Build a Markdown description for a Linear issue from a spec.
174
+ */
175
+ export function buildLinearDescription(spec) {
176
+ const lines = [
177
+ `## ${spec.id}: ${spec.title}`,
178
+ '',
179
+ `**Status:** ${spec.status}`,
180
+ `**Source:** Planu spec`,
181
+ ];
182
+ return lines.join('\n');
183
+ }
184
+ //# sourceMappingURL=linear-exporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-exporter.js","sourceRoot":"","sources":["../../src/engine/linear-exporter.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,19 @@
1
- import type { PlanuConfig } from '../types/index.js';
1
+ import type { PlanuConfig, WorkMode } from '../types/index.js';
2
2
  /**
3
3
  * Create a new PlanuConfig with defaults. Always uses modern spec location.
4
+ * SPEC-313: Accepts optional workMode to embed in the generated config.
4
5
  */
5
- export declare function createPlanuConfig(): PlanuConfig;
6
+ export declare function createPlanuConfig(workMode?: WorkMode): PlanuConfig;
7
+ /**
8
+ * SPEC-313: Read planu.json, update workMode, and write back.
9
+ * Accepts injected readFile/writeFile to keep this function pure/testable.
10
+ */
11
+ export declare function updatePlanuConfigWorkMode(planuConfigPath: string, workMode: WorkMode, readFile: (path: string, enc: 'utf-8') => Promise<string>, writeFile: (path: string, data: string, enc: 'utf-8') => Promise<void>): Promise<void>;
12
+ /**
13
+ * SPEC-313: Read and parse planu.json to retrieve its config (best-effort).
14
+ * Returns null if the file is absent or malformed.
15
+ */
16
+ export declare function readPlanuConfig(planuConfigPath: string, readFile: (path: string, enc: 'utf-8') => Promise<string>): Promise<PlanuConfig | null>;
6
17
  /**
7
18
  * Serialize PlanuConfig to JSON string.
8
19
  */
@@ -1 +1 @@
1
- {"version":3,"file":"planu-config-writer.d.ts","sourceRoot":"","sources":["../../src/engine/planu-config-writer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKrD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,WAAW,CAU/C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAEhE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAKA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAE9D"}
1
+ {"version":3,"file":"planu-config-writer.d.ts","sourceRoot":"","sources":["../../src/engine/planu-config-writer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAK/D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,WAAW,CAWlE;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,EACzD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GACrE,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,GACxD,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAO7B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAEhE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAKA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAE9D"}