specky-sdd 2.2.2 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Checkpoint Tools — sdd_checkpoint, sdd_restore.
3
+ * Snapshot and rollback spec artifacts.
4
+ */
5
+ import { join } from "node:path";
6
+ import { z } from "zod";
7
+ function formatError(toolName, error) {
8
+ return `[${toolName}] Error: ${error.message}`;
9
+ }
10
+ const checkpointInputSchema = z.object({
11
+ feature_number: z
12
+ .string()
13
+ .regex(/^\d{3}$/, "Feature number must be 3 digits")
14
+ .default("001")
15
+ .describe("Feature number (e.g. '001')"),
16
+ spec_dir: z.string().default(".specs").describe("Spec directory path"),
17
+ label: z
18
+ .string()
19
+ .max(100)
20
+ .optional()
21
+ .describe("Human-readable label for this checkpoint (e.g. 'before-redesign', 'v1-approved')"),
22
+ }).strict().describe("Create a named snapshot of all spec artifacts for the feature. Allows rollback to this point later.");
23
+ const restoreInputSchema = z.object({
24
+ feature_number: z
25
+ .string()
26
+ .regex(/^\d{3}$/, "Feature number must be 3 digits")
27
+ .default("001")
28
+ .describe("Feature number (e.g. '001')"),
29
+ spec_dir: z.string().default(".specs").describe("Spec directory path"),
30
+ checkpoint_id: z
31
+ .string()
32
+ .min(1)
33
+ .describe("Checkpoint ID to restore (e.g. 'CP-001' or the label)"),
34
+ }).strict().describe("Restore spec artifacts from a previous checkpoint. Overwrites current artifacts with the checkpoint snapshot.");
35
+ const listCheckpointsInputSchema = z.object({
36
+ feature_number: z
37
+ .string()
38
+ .regex(/^\d{3}$/, "Feature number must be 3 digits")
39
+ .default("001")
40
+ .describe("Feature number (e.g. '001')"),
41
+ spec_dir: z.string().default(".specs").describe("Spec directory path"),
42
+ }).strict().describe("List all available checkpoints for a feature.");
43
+ export function registerCheckpointTools(server, fileManager, stateMachine) {
44
+ // ─── sdd_checkpoint ───
45
+ server.registerTool("sdd_checkpoint", {
46
+ title: "Create Checkpoint",
47
+ description: "Creates a named snapshot of all spec artifacts (CONSTITUTION.md, SPECIFICATION.md, DESIGN.md, TASKS.md, etc.) " +
48
+ "and the current pipeline state. Use before making major changes so you can rollback if needed.",
49
+ inputSchema: checkpointInputSchema,
50
+ annotations: {
51
+ readOnlyHint: false,
52
+ destructiveHint: false,
53
+ idempotentHint: false,
54
+ openWorldHint: false,
55
+ },
56
+ }, async ({ feature_number, spec_dir, label }) => {
57
+ try {
58
+ const features = await fileManager.listFeatures(spec_dir);
59
+ const feature = features.find((f) => f.number === feature_number);
60
+ if (!feature) {
61
+ throw new Error(`Feature ${feature_number} not found in ${spec_dir}. Run sdd_init first.`);
62
+ }
63
+ // Load current state
64
+ const state = await stateMachine.loadState(spec_dir);
65
+ // Determine checkpoint number
66
+ const checkpointsDir = join(feature.directory, ".checkpoints");
67
+ let existingCheckpoints = [];
68
+ try {
69
+ const checkpointFiles = await fileManager.listSpecFiles(checkpointsDir);
70
+ existingCheckpoints = checkpointFiles.filter(f => f.endsWith(".json"));
71
+ }
72
+ catch {
73
+ // Directory doesn't exist yet, that's fine
74
+ }
75
+ const cpNumber = existingCheckpoints.length + 1;
76
+ const cpId = `CP-${String(cpNumber).padStart(3, "0")}`;
77
+ // Snapshot all artifacts
78
+ const artifactNames = [
79
+ "CONSTITUTION.md", "SPECIFICATION.md", "DESIGN.md", "TASKS.md",
80
+ "ANALYSIS.md", "CHECKLIST.md", "VERIFICATION.md", "BUGFIX_SPEC.md",
81
+ "COMPLIANCE.md", "CROSS_ANALYSIS.md",
82
+ ];
83
+ const artifacts = {};
84
+ for (const name of artifactNames) {
85
+ try {
86
+ const content = await fileManager.readSpecFile(feature.directory, name);
87
+ artifacts[name] = content;
88
+ }
89
+ catch {
90
+ // File doesn't exist, skip
91
+ }
92
+ }
93
+ // Build checkpoint payload
94
+ const checkpoint = {
95
+ id: cpId,
96
+ label: label || `Checkpoint ${cpNumber}`,
97
+ created_at: new Date().toISOString(),
98
+ phase: state.current_phase,
99
+ phases: state.phases,
100
+ gate_decision: state.gate_decision,
101
+ artifacts: Object.keys(artifacts),
102
+ artifact_contents: artifacts,
103
+ };
104
+ // Write checkpoint file
105
+ await fileManager.writeSpecFile(checkpointsDir, `${cpId}.json`, JSON.stringify(checkpoint, null, 2), true);
106
+ const result = {
107
+ status: "checkpoint_created",
108
+ checkpoint_id: cpId,
109
+ label: checkpoint.label,
110
+ phase: state.current_phase,
111
+ artifacts_saved: Object.keys(artifacts),
112
+ created_at: checkpoint.created_at,
113
+ next_steps: `Checkpoint ${cpId} saved. You can restore to this point with sdd_restore(checkpoint_id: "${cpId}"). Continue making changes safely.`,
114
+ learning_note: "Checkpoints are snapshots of your spec artifacts at a specific point in time. " +
115
+ "Create checkpoints before major changes (redesigns, scope changes) so you can rollback if the new direction doesn't work out. " +
116
+ "Each checkpoint stores the full content of all artifacts plus the pipeline state.",
117
+ };
118
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
119
+ }
120
+ catch (error) {
121
+ return {
122
+ content: [{ type: "text", text: formatError("sdd_checkpoint", error) }],
123
+ isError: true,
124
+ };
125
+ }
126
+ });
127
+ // ─── sdd_restore ───
128
+ server.registerTool("sdd_restore", {
129
+ title: "Restore from Checkpoint",
130
+ description: "Restores all spec artifacts to a previous checkpoint snapshot. " +
131
+ "Overwrites current files with the checkpoint versions. Creates an automatic backup checkpoint of current state before restoring.",
132
+ inputSchema: restoreInputSchema,
133
+ annotations: {
134
+ readOnlyHint: false,
135
+ destructiveHint: true,
136
+ idempotentHint: false,
137
+ openWorldHint: false,
138
+ },
139
+ }, async ({ feature_number, spec_dir, checkpoint_id }) => {
140
+ try {
141
+ const features = await fileManager.listFeatures(spec_dir);
142
+ const feature = features.find((f) => f.number === feature_number);
143
+ if (!feature) {
144
+ throw new Error(`Feature ${feature_number} not found in ${spec_dir}.`);
145
+ }
146
+ const checkpointsDir = join(feature.directory, ".checkpoints");
147
+ // Find checkpoint by ID or label
148
+ let checkpointContent;
149
+ try {
150
+ // Try direct ID match
151
+ checkpointContent = await fileManager.readSpecFile(checkpointsDir, `${checkpoint_id}.json`);
152
+ }
153
+ catch {
154
+ // Try finding by label
155
+ const files = await fileManager.listSpecFiles(checkpointsDir);
156
+ let found = false;
157
+ for (const file of files) {
158
+ if (!file.endsWith(".json"))
159
+ continue;
160
+ const content = await fileManager.readSpecFile(checkpointsDir, file);
161
+ const cp = JSON.parse(content);
162
+ if (cp.label === checkpoint_id || cp.id === checkpoint_id) {
163
+ checkpointContent = content;
164
+ found = true;
165
+ break;
166
+ }
167
+ }
168
+ if (!found) {
169
+ throw new Error(`Checkpoint "${checkpoint_id}" not found. Use sdd_list_checkpoints to see available checkpoints.`);
170
+ }
171
+ }
172
+ const checkpoint = JSON.parse(checkpointContent);
173
+ // Auto-backup current state before restoring
174
+ const backupArtifacts = {};
175
+ for (const name of Object.keys(checkpoint.artifact_contents)) {
176
+ try {
177
+ const current = await fileManager.readSpecFile(feature.directory, name);
178
+ backupArtifacts[name] = current;
179
+ }
180
+ catch {
181
+ // Current file doesn't exist
182
+ }
183
+ }
184
+ const state = await stateMachine.loadState(spec_dir);
185
+ const autoBackup = {
186
+ id: "CP-AUTO-BACKUP",
187
+ label: `Auto-backup before restoring ${checkpoint.id}`,
188
+ created_at: new Date().toISOString(),
189
+ phase: state.current_phase,
190
+ phases: state.phases,
191
+ gate_decision: state.gate_decision,
192
+ artifacts: Object.keys(backupArtifacts),
193
+ artifact_contents: backupArtifacts,
194
+ };
195
+ await fileManager.writeSpecFile(checkpointsDir, "CP-AUTO-BACKUP.json", JSON.stringify(autoBackup, null, 2), true);
196
+ // Restore artifacts
197
+ const restored = [];
198
+ for (const [name, content] of Object.entries(checkpoint.artifact_contents)) {
199
+ await fileManager.writeSpecFile(feature.directory, name, content, true);
200
+ restored.push(name);
201
+ }
202
+ // Restore pipeline state
203
+ if (checkpoint.phases) {
204
+ state.current_phase = checkpoint.phase;
205
+ state.phases = checkpoint.phases;
206
+ state.gate_decision = checkpoint.gate_decision || null;
207
+ await stateMachine.saveState(spec_dir, state);
208
+ }
209
+ const result = {
210
+ status: "checkpoint_restored",
211
+ checkpoint_id: checkpoint.id,
212
+ checkpoint_label: checkpoint.label,
213
+ restored_phase: checkpoint.phase,
214
+ restored_artifacts: restored,
215
+ auto_backup: "CP-AUTO-BACKUP",
216
+ next_steps: `Restored to ${checkpoint.id} ("${checkpoint.label}"). Current state before restore was saved as CP-AUTO-BACKUP. Review the restored artifacts and continue from the ${checkpoint.phase} phase.`,
217
+ learning_note: "The restore operation creates an automatic backup of your current state before overwriting. " +
218
+ "This means you can always undo a restore by running sdd_restore(checkpoint_id: 'CP-AUTO-BACKUP').",
219
+ };
220
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
221
+ }
222
+ catch (error) {
223
+ return {
224
+ content: [{ type: "text", text: formatError("sdd_restore", error) }],
225
+ isError: true,
226
+ };
227
+ }
228
+ });
229
+ // ─── sdd_list_checkpoints ───
230
+ server.registerTool("sdd_list_checkpoints", {
231
+ title: "List Checkpoints",
232
+ description: "Lists all available checkpoints for a feature with their labels, dates, and phases.",
233
+ inputSchema: listCheckpointsInputSchema,
234
+ annotations: {
235
+ readOnlyHint: true,
236
+ destructiveHint: false,
237
+ idempotentHint: true,
238
+ openWorldHint: false,
239
+ },
240
+ }, async ({ feature_number, spec_dir }) => {
241
+ try {
242
+ const features = await fileManager.listFeatures(spec_dir);
243
+ const feature = features.find((f) => f.number === feature_number);
244
+ if (!feature) {
245
+ throw new Error(`Feature ${feature_number} not found in ${spec_dir}.`);
246
+ }
247
+ const checkpointsDir = join(feature.directory, ".checkpoints");
248
+ let files;
249
+ try {
250
+ files = await fileManager.listSpecFiles(checkpointsDir);
251
+ }
252
+ catch {
253
+ return {
254
+ content: [{
255
+ type: "text",
256
+ text: JSON.stringify({
257
+ status: "no_checkpoints",
258
+ checkpoints: [],
259
+ next_steps: "No checkpoints found. Use sdd_checkpoint to create one before making major changes.",
260
+ }, null, 2),
261
+ }],
262
+ };
263
+ }
264
+ const checkpoints = [];
265
+ for (const file of files) {
266
+ if (!file.endsWith(".json"))
267
+ continue;
268
+ try {
269
+ const content = await fileManager.readSpecFile(checkpointsDir, file);
270
+ const cp = JSON.parse(content);
271
+ checkpoints.push({
272
+ id: cp.id,
273
+ label: cp.label,
274
+ created_at: cp.created_at,
275
+ phase: cp.phase,
276
+ artifacts: cp.artifacts || [],
277
+ });
278
+ }
279
+ catch {
280
+ // Skip corrupted checkpoint files
281
+ }
282
+ }
283
+ // Sort by creation date (newest first)
284
+ checkpoints.sort((a, b) => b.created_at.localeCompare(a.created_at));
285
+ const result = {
286
+ status: "checkpoints_listed",
287
+ total: checkpoints.length,
288
+ checkpoints,
289
+ next_steps: checkpoints.length > 0
290
+ ? `Use sdd_restore(checkpoint_id: "${checkpoints[0].id}") to restore to any checkpoint.`
291
+ : "No checkpoints yet. Use sdd_checkpoint to create one.",
292
+ };
293
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
294
+ }
295
+ catch (error) {
296
+ return {
297
+ content: [{ type: "text", text: formatError("sdd_list_checkpoints", error) }],
298
+ isError: true,
299
+ };
300
+ }
301
+ });
302
+ }
303
+ //# sourceMappingURL=checkpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint.js","sourceRoot":"","sources":["../../src/tools/checkpoint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * PBT Tools — sdd_generate_pbt.
3
+ */
4
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import type { FileManager } from "../services/file-manager.js";
6
+ import type { StateMachine } from "../services/state-machine.js";
7
+ import type { PbtGenerator } from "../services/pbt-generator.js";
8
+ export declare function registerPbtTools(server: McpServer, fileManager: FileManager, _stateMachine: StateMachine, pbtGenerator: PbtGenerator): void;
9
+ //# sourceMappingURL=pbt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pbt.d.ts","sourceRoot":"","sources":["../../src/tools/pbt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAYjE,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,YAAY,EAC3B,YAAY,EAAE,YAAY,GACzB,IAAI,CAuFN"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * PBT Tools — sdd_generate_pbt.
3
+ */
4
+ import { CHARACTER_LIMIT } from "../constants.js";
5
+ import { generatePbtInputSchema } from "../schemas/pbt.js";
6
+ function formatError(toolName, error) {
7
+ return `[${toolName}] Error: ${error.message}`;
8
+ }
9
+ function truncate(text) {
10
+ if (text.length <= CHARACTER_LIMIT)
11
+ return text;
12
+ return text.slice(0, CHARACTER_LIMIT) + "\n\n[TRUNCATED] Response exceeded 25,000 characters.";
13
+ }
14
+ export function registerPbtTools(server, fileManager, _stateMachine, pbtGenerator) {
15
+ server.registerTool("sdd_generate_pbt", {
16
+ title: "Generate Property-Based Tests",
17
+ description: "Extracts universal properties (invariants, round-trips, idempotence) from EARS requirements " +
18
+ "and generates property-based tests using fast-check (TypeScript) or hypothesis (Python). " +
19
+ "Unlike example-based tests, PBT uses random input generation to discover edge cases that manual tests miss.",
20
+ inputSchema: generatePbtInputSchema,
21
+ annotations: {
22
+ readOnlyHint: false,
23
+ destructiveHint: false,
24
+ idempotentHint: false,
25
+ openWorldHint: false,
26
+ },
27
+ }, async ({ framework, feature_number, spec_dir, output_dir }) => {
28
+ try {
29
+ const features = await fileManager.listFeatures(spec_dir);
30
+ const feature = features.find((f) => f.number === feature_number);
31
+ if (!feature) {
32
+ throw new Error(`Feature ${feature_number} not found in ${spec_dir}. Run sdd_init first.`);
33
+ }
34
+ const genResult = await pbtGenerator.generate(feature.directory, framework, output_dir);
35
+ const fileName = genResult.output_file.split("/").pop() || genResult.output_file;
36
+ const dirPart = genResult.output_file.replace(/\/[^/]+$/, "");
37
+ await fileManager.writeSpecFile(dirPart, fileName, genResult.content, true);
38
+ const traceability = genResult.properties.map((p) => ({
39
+ prop_id: p.id,
40
+ requirement: p.requirement_id,
41
+ type: p.property_type,
42
+ description: p.description,
43
+ }));
44
+ const frameworkLabel = framework === "fast-check" ? "fast-check" : "hypothesis";
45
+ const result = {
46
+ status: "pbt_generated",
47
+ framework: genResult.framework,
48
+ total_properties: genResult.total_properties,
49
+ property_types: genResult.property_types,
50
+ output_file: genResult.output_file,
51
+ content: genResult.content,
52
+ traceability,
53
+ next_steps: `Install ${frameworkLabel}, run the tests, and review failing properties. ` +
54
+ "Each failure includes a minimal counterexample — this is the key advantage of PBT over example-based testing.",
55
+ learning_note: "Property-based testing verifies universal truths about your system rather than specific examples. " +
56
+ "EARS requirements map naturally to properties: ubiquitous requirements become invariants, " +
57
+ "event-driven become state transitions, and unwanted behaviors become negative properties. " +
58
+ "When a PBT fails, the framework 'shrinks' the input to the smallest example that triggers the failure.",
59
+ };
60
+ return {
61
+ content: [
62
+ { type: "text", text: truncate(JSON.stringify(result, null, 2)) },
63
+ ],
64
+ };
65
+ }
66
+ catch (error) {
67
+ return {
68
+ content: [
69
+ {
70
+ type: "text",
71
+ text: formatError("sdd_generate_pbt", error),
72
+ },
73
+ ],
74
+ isError: true,
75
+ };
76
+ }
77
+ });
78
+ }
79
+ //# sourceMappingURL=pbt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pbt.js","sourceRoot":"","sources":["../../src/tools/pbt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Turnkey Tool — sdd_turnkey_spec.
3
+ * Generates full EARS specification from a natural language description.
4
+ */
5
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import type { FileManager } from "../services/file-manager.js";
7
+ import type { StateMachine } from "../services/state-machine.js";
8
+ import type { TemplateEngine } from "../services/template-engine.js";
9
+ import type { EarsValidator } from "../services/ears-validator.js";
10
+ export declare function registerTurnkeyTools(server: McpServer, fileManager: FileManager, stateMachine: StateMachine, templateEngine: TemplateEngine, earsValidator: EarsValidator): void;
11
+ export interface RequirementCandidate {
12
+ text: string;
13
+ type: "functional" | "behavior" | "constraint" | "error_handling";
14
+ confidence: number;
15
+ }
16
+ export declare function extractRequirementCandidates(description: string): RequirementCandidate[];
17
+ export declare function deduplicateCandidates(candidates: RequirementCandidate[]): RequirementCandidate[];
18
+ export declare function convertToEars(candidate: RequirementCandidate): string;
19
+ export declare function generateAcceptanceCriteria(candidate: RequirementCandidate, earsText: string): string[];
20
+ export declare function generateClarifications(description: string, requirements: Array<{
21
+ id: string;
22
+ text: string;
23
+ valid: boolean;
24
+ issues?: string[];
25
+ }>): Array<{
26
+ id: string;
27
+ question: string;
28
+ context: string;
29
+ }>;
30
+ export declare function inferNonFunctionalRequirements(description: string): Array<{
31
+ text: string;
32
+ criterion: string;
33
+ }>;
34
+ export declare function countPatterns(requirements: Array<{
35
+ ears_pattern: string;
36
+ }>): Record<string, number>;
37
+ //# sourceMappingURL=turnkey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turnkey.d.ts","sourceRoot":"","sources":["../../src/tools/turnkey.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAyCnE,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,YAAY,EAC1B,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,aAAa,GAC3B,IAAI,CAyKN;AAID,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,YAAY,GAAG,gBAAgB,CAAC;IAClE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAqExF;AAED,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,oBAAoB,EAAE,GAAG,oBAAoB,EAAE,CAYhG;AAYD,wBAAgB,aAAa,CAAC,SAAS,EAAE,oBAAoB,GAAG,MAAM,CAwCrE;AAiFD,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAqCtG;AAED,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,GACnF,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA0C1D;AAED,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA2B9G;AAED,wBAAgB,aAAa,CAAC,YAAY,EAAE,KAAK,CAAC;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMnG"}