pdd-cli 0.0.61__py3-none-any.whl → 0.0.63__py3-none-any.whl

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.

Potentially problematic release.


This version of pdd-cli might be problematic. Click here for more details.

pdd/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """PDD - Prompt Driven Development"""
2
2
 
3
- __version__ = "0.0.61"
3
+ __version__ = "0.0.63"
4
4
 
5
5
  # Strength parameter used for LLM extraction across the codebase
6
6
  # Used in postprocessing, XML tagging, code generation, and other extraction
pdd/cli.py CHANGED
@@ -14,9 +14,11 @@ from typing import Any, Dict, List, Optional, Tuple
14
14
  from pathlib import Path # Import Path
15
15
 
16
16
  import click
17
+ from rich import box
17
18
  from rich.console import Console
18
- from rich.theme import Theme
19
19
  from rich.markup import MarkupError, escape
20
+ from rich.table import Table
21
+ from rich.theme import Theme
20
22
 
21
23
  # --- Relative Imports for Internal Modules ---
22
24
  from . import DEFAULT_STRENGTH, __version__, DEFAULT_TIME
@@ -449,20 +451,138 @@ def templates_show(name: str):
449
451
  try:
450
452
  data = template_registry.show_template(name)
451
453
  summary = data.get("summary", {})
452
- console.print(f"[bold]{summary.get('name','')}[/bold] — {summary.get('description','')}")
453
- console.print(f"Version: {summary.get('version','')} Tags: {', '.join(summary.get('tags',[]))}")
454
- console.print(f"Language: {summary.get('language','')} Output: {summary.get('output','')}")
455
- console.print(f"Path: {summary.get('path','')}")
454
+
455
+ def _render_key_value_table(title: Optional[str], items: List[Tuple[str, Any]], *, highlight_path: bool = False):
456
+ """Render a 2-column Rich table for key/value pairs."""
457
+
458
+ table = Table(show_header=False, box=box.SIMPLE, expand=True)
459
+ table.add_column("Field", style="info", no_wrap=True)
460
+ table.add_column("Value", overflow="fold")
461
+
462
+ added_rows = False
463
+ for label, value in items:
464
+ if value in (None, "", [], {}):
465
+ continue
466
+ if isinstance(value, (list, tuple)):
467
+ value_str = ", ".join(str(v) for v in value)
468
+ else:
469
+ value_str = str(value)
470
+
471
+ if highlight_path and label.lower() == "path":
472
+ value_markup = f"[path]{escape(value_str)}[/path]"
473
+ else:
474
+ value_markup = escape(value_str)
475
+
476
+ table.add_row(label, value_markup)
477
+ added_rows = True
478
+
479
+ if added_rows:
480
+ if title:
481
+ console.print(f"[info]{title}[/info]")
482
+ console.print(table)
483
+
484
+ summary_items = [
485
+ ("Name", summary.get("name")),
486
+ ("Description", summary.get("description")),
487
+ ("Version", summary.get("version")),
488
+ ("Tags", summary.get("tags", [])),
489
+ ("Language", summary.get("language")),
490
+ ("Output", summary.get("output")),
491
+ ("Path", summary.get("path")),
492
+ ]
493
+ _render_key_value_table("Template Summary:", summary_items, highlight_path=True)
494
+
456
495
  if data.get("variables"):
457
496
  console.print("\n[info]Variables:[/info]")
458
- for k, v in data["variables"].items():
459
- console.print(f"- {k}: {v}")
497
+ variables_table = Table(box=box.SIMPLE_HEAD, show_lines=False, expand=True)
498
+ variables_table.add_column("Name", style="bold", no_wrap=True)
499
+ variables_table.add_column("Required", style="info", no_wrap=True)
500
+ variables_table.add_column("Type", no_wrap=True)
501
+ variables_table.add_column("Description", overflow="fold")
502
+ variables_table.add_column("Default/Examples", overflow="fold")
503
+
504
+ for var_name, var_meta in data["variables"].items():
505
+ required = var_meta.get("required")
506
+ if required is True:
507
+ required_str = "Yes"
508
+ elif required is False:
509
+ required_str = "No"
510
+ else:
511
+ required_str = "-"
512
+
513
+ var_type = escape(str(var_meta.get("type", "-")))
514
+ description = escape(str(var_meta.get("description", "")))
515
+
516
+ default_parts: List[str] = []
517
+ default_value = var_meta.get("default")
518
+ if default_value not in (None, ""):
519
+ default_parts.append(f"default: {default_value}")
520
+
521
+ examples_value = var_meta.get("examples")
522
+ if examples_value:
523
+ if isinstance(examples_value, (list, tuple)):
524
+ examples_str = ", ".join(str(example) for example in examples_value)
525
+ else:
526
+ examples_str = str(examples_value)
527
+ default_parts.append(f"examples: {examples_str}")
528
+
529
+ example_paths_value = var_meta.get("example_paths")
530
+ if example_paths_value:
531
+ if isinstance(example_paths_value, (list, tuple)):
532
+ example_paths_str = ", ".join(str(example) for example in example_paths_value)
533
+ else:
534
+ example_paths_str = str(example_paths_value)
535
+ default_parts.append(f"paths: {example_paths_str}")
536
+
537
+ default_examples = "\n".join(default_parts) if default_parts else "-"
538
+
539
+ variables_table.add_row(
540
+ escape(str(var_name)),
541
+ required_str,
542
+ var_type,
543
+ description,
544
+ escape(default_examples),
545
+ )
546
+
547
+ console.print(variables_table)
548
+
460
549
  if data.get("usage"):
461
550
  console.print("\n[info]Usage:[/info]")
462
- console.print(data["usage"]) # raw; CLI may format later
551
+ usage = data["usage"]
552
+ if isinstance(usage, dict):
553
+ for group_name, entries in usage.items():
554
+ console.print(f"[bold]{escape(str(group_name))}[/bold]")
555
+ usage_table = Table(box=box.SIMPLE, show_lines=False, expand=True)
556
+ usage_table.add_column("Name", style="bold", no_wrap=True)
557
+ usage_table.add_column("Command", overflow="fold")
558
+
559
+ if isinstance(entries, (list, tuple)):
560
+ iterable_entries = entries
561
+ else:
562
+ iterable_entries = [entries]
563
+
564
+ for entry in iterable_entries:
565
+ if isinstance(entry, dict):
566
+ name_value = escape(str(entry.get("name", "")))
567
+ command_value = escape(str(entry.get("command", "")))
568
+ else:
569
+ name_value = "-"
570
+ command_value = escape(str(entry))
571
+ usage_table.add_row(name_value, f"[command]{command_value}[/command]")
572
+
573
+ if usage_table.row_count:
574
+ console.print(usage_table)
575
+ else:
576
+ console.print(usage)
577
+
463
578
  if data.get("discover"):
464
579
  console.print("\n[info]Discover:[/info]")
465
- console.print(data["discover"]) # raw dict
580
+ discover = data["discover"]
581
+ if isinstance(discover, dict):
582
+ discover_items = [(str(key), value) for key, value in discover.items()]
583
+ _render_key_value_table(None, discover_items)
584
+ else:
585
+ console.print(discover)
466
586
  if data.get("output_schema"):
467
587
  console.print("\n[info]Output Schema:[/info]")
468
588
  try:
@@ -64,3 +64,6 @@ Log,del,.log
64
64
  reStructuredText,del,.rst
65
65
  Text,del,.txt
66
66
  INI,;,.ini
67
+ Verilog,//,.v
68
+ Systemverilog,//,.sv
69
+ Prisma,///,.prisma
pdd/data/llm_model.csv CHANGED
@@ -2,7 +2,7 @@ provider,model,input,output,coding_arena_elo,base_url,api_key,max_reasoning_toke
2
2
  OpenAI,gpt-5-nano,0.05,0.4,1249,,OPENAI_API_KEY,0,True,none
3
3
  Google,vertex_ai/gemini-2.5-flash,0.15,0.6,1290,,VERTEX_CREDENTIALS,0,True,effort
4
4
  Google,gemini/gemini-2.5-pro,1.25,10.0,1360,,GEMINI_API_KEY,0,True,none
5
- Google,vertex_ai/claude-sonnet-4,3.0,15.0,1359,,VERTEX_CREDENTIALS,64000,True,budget
5
+ Google,vertex_ai/claude-sonnet-4-5,3.0,15.0,1359,,VERTEX_CREDENTIALS,64000,True,budget
6
6
  Google,vertex_ai/gemini-2.5-pro,1.25,10.0,1405,,VERTEX_CREDENTIALS,0,True,none
7
7
  OpenAI,gpt-5-mini,0.25,2.0,1325,,OPENAI_API_KEY,0,True,effort
8
8
  OpenAI,gpt-5,1.25,10.0,1482,,OPENAI_API_KEY,0,True,effort
@@ -15,6 +15,6 @@ OpenAI,openai/mlx-community/Qwen3-30B-A3B-4bit,0,0,1040,http://localhost:8080,,0
15
15
  OpenAI,lm_studio/openai-gpt-oss-120b-mlx-6,0.0001,0,1082,http://localhost:1234/v1,,0,True,none
16
16
  Fireworks,fireworks_ai/accounts/fireworks/models/glm-4p5,3.0,8.0,1364,,FIREWORKS_API_KEY,0,False,none
17
17
  OpenAI,groq/moonshotai/kimi-k2-instruct,1.0,3.0,1330,,GROQ_API_KEY,0,True,none
18
- Anthropic,anthropic/claude-sonnet-4-20250514,3.0,15.0,1356,,ANTHROPIC_API_KEY,64000,True,budget
18
+ Anthropic,anthropic/claude-sonnet-4-5-20250929,3.0,15.0,1356,,ANTHROPIC_API_KEY,64000,True,budget
19
19
  Anthropic,anthropic/claude-opus-4-1-20250805,3.0,15.0,1474,,ANTHROPIC_API_KEY,32000,True,budget
20
20
  Anthropic,anthropic/claude-3-5-haiku-20241022,3.0,15.0,1133,,ANTHROPIC_API_KEY,8192,True,budget
pdd/preprocess.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  import re
3
3
  import subprocess
4
- from typing import List, Optional
4
+ from typing import List, Optional, Tuple
5
5
  import traceback
6
6
  from rich.console import Console
7
7
  from rich.panel import Panel
@@ -11,22 +11,110 @@ from rich.traceback import install
11
11
  install()
12
12
  console = Console()
13
13
 
14
+ # Debug/Instrumentation controls
15
+ _DEBUG_PREPROCESS = str(os.getenv("PDD_PREPROCESS_DEBUG", "")).lower() in ("1", "true", "yes", "on")
16
+ _DEBUG_OUTPUT_FILE = os.getenv("PDD_PREPROCESS_DEBUG_FILE") # Optional path to write a debug report
17
+ _DEBUG_EVENTS: List[str] = []
18
+
19
+ def _dbg(msg: str) -> None:
20
+ if _DEBUG_PREPROCESS:
21
+ console.print(f"[dim][PPD][preprocess][/dim] {escape(msg)}")
22
+ _DEBUG_EVENTS.append(msg)
23
+
24
+ def _write_debug_report() -> None:
25
+ if _DEBUG_PREPROCESS and _DEBUG_OUTPUT_FILE:
26
+ try:
27
+ with open(_DEBUG_OUTPUT_FILE, "w", encoding="utf-8") as fh:
28
+ fh.write("Preprocess Debug Report\n\n")
29
+ for line in _DEBUG_EVENTS:
30
+ fh.write(line + "\n")
31
+ console.print(f"[green]Debug report written to:[/green] {_DEBUG_OUTPUT_FILE}")
32
+ except Exception as e:
33
+ # Report the error so users know why the log file wasn't written
34
+ console.print(f"[yellow]Warning: Could not write debug report to {_DEBUG_OUTPUT_FILE}: {e}[/yellow]")
35
+ elif _DEBUG_PREPROCESS and not _DEBUG_OUTPUT_FILE:
36
+ console.print("[dim]Debug mode enabled but PDD_PREPROCESS_DEBUG_FILE not set (output shown in console only)[/dim]")
37
+
38
+ def _extract_fence_spans(text: str) -> List[Tuple[int, int]]:
39
+ """Return list of (start, end) spans for fenced code blocks ```...```.
40
+
41
+ The spans are [start, end) indices in the original text.
42
+ """
43
+ spans: List[Tuple[int, int]] = []
44
+ try:
45
+ for m in re.finditer(r"```[\w\s]*\n[\s\S]*?```", text):
46
+ spans.append((m.start(), m.end()))
47
+ except Exception:
48
+ pass
49
+ return spans
50
+
51
+ def _is_inside_any_span(idx: int, spans: List[Tuple[int, int]]) -> bool:
52
+ for s, e in spans:
53
+ if s <= idx < e:
54
+ return True
55
+ return False
56
+
57
+ def _scan_risky_placeholders(text: str) -> Tuple[List[Tuple[int, str]], List[Tuple[int, str]]]:
58
+ """Scan for risky placeholders outside code fences.
59
+
60
+ Returns two lists of (line_no, snippet):
61
+ - single_brace: matches like {name} not doubled and not part of {{...}}
62
+ - template_brace: `${...}` occurrences (which include single { ... })
63
+ """
64
+ single_brace: List[Tuple[int, str]] = []
65
+ template_brace: List[Tuple[int, str]] = []
66
+ try:
67
+ fence_spans = _extract_fence_spans(text)
68
+ # Single-brace variable placeholders (avoid matching {{ or }})
69
+ for m in re.finditer(r"(?<!\{)\{([A-Za-z_][A-Za-z0-9_]*)\}(?!\})", text):
70
+ if not _is_inside_any_span(m.start(), fence_spans):
71
+ line_no = text.count("\n", 0, m.start()) + 1
72
+ single_brace.append((line_no, m.group(0)))
73
+ # JavaScript template placeholders like ${...}
74
+ for m in re.finditer(r"\$\{[^\}]+\}", text):
75
+ if not _is_inside_any_span(m.start(), fence_spans):
76
+ line_no = text.count("\n", 0, m.start()) + 1
77
+ template_brace.append((line_no, m.group(0)))
78
+ except Exception:
79
+ pass
80
+ return single_brace, template_brace
81
+
14
82
  def preprocess(prompt: str, recursive: bool = False, double_curly_brackets: bool = True, exclude_keys: Optional[List[str]] = None) -> str:
15
83
  try:
16
84
  if not prompt:
17
85
  console.print("[bold red]Error:[/bold red] Empty prompt provided")
18
86
  return ""
87
+ _DEBUG_EVENTS.clear()
88
+ _dbg(f"Start preprocess(recursive={recursive}, double_curly={double_curly_brackets}, exclude_keys={exclude_keys})")
89
+ _dbg(f"Initial length: {len(prompt)} characters")
19
90
  console.print(Panel("Starting prompt preprocessing", style="bold blue"))
20
91
  prompt = process_backtick_includes(prompt, recursive)
92
+ _dbg("After backtick includes processed")
21
93
  prompt = process_xml_tags(prompt, recursive)
94
+ _dbg("After XML-like tags processed")
22
95
  if double_curly_brackets:
23
96
  prompt = double_curly(prompt, exclude_keys)
97
+ _dbg("After double_curly execution")
98
+ # Scan for risky placeholders remaining outside code fences
99
+ singles, templates = _scan_risky_placeholders(prompt)
100
+ if singles:
101
+ _dbg(f"WARNING: Found {len(singles)} single-brace placeholders outside code fences (examples):")
102
+ for ln, frag in singles[:5]:
103
+ _dbg(f" line {ln}: {frag}")
104
+ if templates:
105
+ _dbg(f"INFO: Found {len(templates)} template literals ${'{...'} outside code fences (examples):")
106
+ for ln, frag in templates[:5]:
107
+ _dbg(f" line {ln}: {frag}")
24
108
  # Don't trim whitespace that might be significant for the tests
25
109
  console.print(Panel("Preprocessing complete", style="bold green"))
110
+ _dbg(f"Final length: {len(prompt)} characters")
111
+ _write_debug_report()
26
112
  return prompt
27
113
  except Exception as e:
28
114
  console.print(f"[bold red]Error during preprocessing:[/bold red] {str(e)}")
29
115
  console.print(Panel(traceback.format_exc(), title="Error Details", style="red"))
116
+ _dbg(f"Exception: {str(e)}")
117
+ _write_debug_report()
30
118
  return prompt
31
119
 
32
120
  def get_file_path(file_name: str) -> str:
@@ -45,14 +133,17 @@ def process_backtick_includes(text: str, recursive: bool) -> str:
45
133
  content = file.read()
46
134
  if recursive:
47
135
  content = preprocess(content, recursive=True, double_curly_brackets=False)
136
+ _dbg(f"Included via backticks: {file_path} (len={len(content)})")
48
137
  return f"```{content}```"
49
138
  except FileNotFoundError:
50
139
  console.print(f"[bold red]Warning:[/bold red] File not found: {file_path}")
140
+ _dbg(f"Missing backtick include: {file_path}")
51
141
  # First pass (recursive=True): leave the tag so a later env expansion can resolve it
52
142
  # Second pass (recursive=False): replace with a visible placeholder
53
143
  return match.group(0) if recursive else f"```[File not found: {file_path}]```"
54
144
  except Exception as e:
55
145
  console.print(f"[bold red]Error processing include:[/bold red] {str(e)}")
146
+ _dbg(f"Error processing backtick include {file_path}: {e}")
56
147
  return f"```[Error processing include: {file_path}]```"
57
148
  prev_text = ""
58
149
  current_text = text
@@ -80,14 +171,17 @@ def process_include_tags(text: str, recursive: bool) -> str:
80
171
  content = file.read()
81
172
  if recursive:
82
173
  content = preprocess(content, recursive=True, double_curly_brackets=False)
174
+ _dbg(f"Included via XML tag: {file_path} (len={len(content)})")
83
175
  return content
84
176
  except FileNotFoundError:
85
177
  console.print(f"[bold red]Warning:[/bold red] File not found: {file_path}")
178
+ _dbg(f"Missing XML include: {file_path}")
86
179
  # First pass (recursive=True): leave the tag so a later env expansion can resolve it
87
180
  # Second pass (recursive=False): replace with a visible placeholder
88
181
  return match.group(0) if recursive else f"[File not found: {file_path}]"
89
182
  except Exception as e:
90
183
  console.print(f"[bold red]Error processing include:[/bold red] {str(e)}")
184
+ _dbg(f"Error processing XML include {file_path}: {e}")
91
185
  return f"[Error processing include: {file_path}]"
92
186
  prev_text = ""
93
187
  current_text = text
@@ -113,15 +207,18 @@ def process_shell_tags(text: str, recursive: bool) -> str:
113
207
  # Defer execution until after env var expansion
114
208
  return match.group(0)
115
209
  console.print(f"Executing shell command: [cyan]{escape(command)}[/cyan]")
210
+ _dbg(f"Shell tag command: {command}")
116
211
  try:
117
212
  result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True)
118
213
  return result.stdout
119
214
  except subprocess.CalledProcessError as e:
120
215
  error_msg = f"Command '{command}' returned non-zero exit status {e.returncode}."
121
216
  console.print(f"[bold red]Error:[/bold red] {error_msg}")
217
+ _dbg(f"Shell command error: {error_msg}")
122
218
  return f"Error: {error_msg}"
123
219
  except Exception as e:
124
220
  console.print(f"[bold red]Error executing shell command:[/bold red] {str(e)}")
221
+ _dbg(f"Shell execution exception: {e}")
125
222
  return f"[Shell execution error: {str(e)}]"
126
223
  return re.sub(pattern, replace_shell, text, flags=re.DOTALL)
127
224
 
@@ -133,24 +230,30 @@ def process_web_tags(text: str, recursive: bool) -> str:
133
230
  # Defer network operations until after env var expansion
134
231
  return match.group(0)
135
232
  console.print(f"Scraping web content from: [cyan]{url}[/cyan]")
233
+ _dbg(f"Web tag URL: {url}")
136
234
  try:
137
235
  try:
138
236
  from firecrawl import FirecrawlApp
139
237
  except ImportError:
238
+ _dbg("firecrawl import failed; package not installed")
140
239
  return f"[Error: firecrawl-py package not installed. Cannot scrape {url}]"
141
240
  api_key = os.environ.get('FIRECRAWL_API_KEY')
142
241
  if not api_key:
143
242
  console.print("[bold yellow]Warning:[/bold yellow] FIRECRAWL_API_KEY not found in environment")
243
+ _dbg("FIRECRAWL_API_KEY not set")
144
244
  return f"[Error: FIRECRAWL_API_KEY not set. Cannot scrape {url}]"
145
245
  app = FirecrawlApp(api_key=api_key)
146
246
  response = app.scrape_url(url, formats=['markdown'])
147
247
  if hasattr(response, 'markdown'):
248
+ _dbg(f"Web scrape returned markdown (len={len(response.markdown)})")
148
249
  return response.markdown
149
250
  else:
150
251
  console.print(f"[bold yellow]Warning:[/bold yellow] No markdown content returned for {url}")
252
+ _dbg("Web scrape returned no markdown content")
151
253
  return f"[No content available for {url}]"
152
254
  except Exception as e:
153
255
  console.print(f"[bold red]Error scraping web content:[/bold red] {str(e)}")
256
+ _dbg(f"Web scraping exception: {e}")
154
257
  return f"[Web scraping error: {str(e)}]"
155
258
  return re.sub(pattern, replace_web, text, flags=re.DOTALL)
156
259
 
@@ -173,11 +276,14 @@ def process_include_many_tags(text: str, recursive: bool) -> str:
173
276
  console.print(f"Including (many): [cyan]{full_path}[/cyan]")
174
277
  with open(full_path, 'r', encoding='utf-8') as fh:
175
278
  contents.append(fh.read())
279
+ _dbg(f"Included (many): {p}")
176
280
  except FileNotFoundError:
177
281
  console.print(f"[bold red]Warning:[/bold red] File not found: {p}")
282
+ _dbg(f"Missing include-many: {p}")
178
283
  contents.append(f"[File not found: {p}]")
179
284
  except Exception as e:
180
285
  console.print(f"[bold red]Error processing include-many:[/bold red] {str(e)}")
286
+ _dbg(f"Error processing include-many {p}: {e}")
181
287
  contents.append(f"[Error processing include: {p}]")
182
288
  return "\n".join(contents)
183
289
  return re.sub(pattern, replace_many, text, flags=re.DOTALL)
@@ -187,6 +293,7 @@ def double_curly(text: str, exclude_keys: Optional[List[str]] = None) -> str:
187
293
  exclude_keys = []
188
294
 
189
295
  console.print("Doubling curly brackets...")
296
+ _dbg("double_curly invoked")
190
297
 
191
298
  # Special case handling for specific test patterns
192
299
  if "Mix of {excluded{inner}} nesting" in text and "excluded" in exclude_keys:
@@ -210,8 +317,8 @@ def double_curly(text: str, exclude_keys: Optional[List[str]] = None) -> str:
210
317
  "2": {{"id": "2", "name": "Resource Two"}}
211
318
  }}"""
212
319
 
213
- # Protect ${IDENT} placeholders so they remain unchanged
214
- # Use placeholders that won't collide with typical content
320
+ # Protect ${IDENT} placeholders so we can safely double braces, then restore
321
+ # them as ${{IDENT}} to avoid PromptTemplate interpreting {IDENT}.
215
322
  protected_vars: List[str] = []
216
323
  def _protect_var(m):
217
324
  protected_vars.append(m.group(0))
@@ -235,10 +342,22 @@ def double_curly(text: str, exclude_keys: Optional[List[str]] = None) -> str:
235
342
  # Restore already doubled brackets
236
343
  text = re.sub(r'__ALREADY_DOUBLED__(.*?)__END_ALREADY__', r'{{\1}}', text)
237
344
 
238
- # Restore protected ${IDENT} placeholders
345
+ # Restore protected ${IDENT} placeholders as ${{IDENT}} so single braces
346
+ # don't leak into PromptTemplate formatting. This is safe for JS template
347
+ # literals and prevents missing-key errors in later formatting steps.
239
348
  def _restore_var(m):
240
349
  idx = int(m.group(1))
241
- return protected_vars[idx] if 0 <= idx < len(protected_vars) else m.group(0)
350
+ if 0 <= idx < len(protected_vars):
351
+ original = protected_vars[idx] # e.g., ${FOO}
352
+ try:
353
+ inner = re.match(r"\$\{([A-Za-z_][A-Za-z0-9_]*)\}", original)
354
+ if inner:
355
+ # Build as concatenation to avoid f-string brace escaping confusion
356
+ return "${{" + inner.group(1) + "}}" # -> ${{FOO}}
357
+ except Exception:
358
+ pass
359
+ return original
360
+ return m.group(0)
242
361
  text = re.sub(r"__PDD_VAR_(\d+)__", _restore_var, text)
243
362
 
244
363
  # Special handling for code blocks
@@ -66,13 +66,14 @@ output_schema:
66
66
  type: array
67
67
  items:
68
68
  type: object
69
- required: [reason, description, dependencies, priority, filename]
69
+ required: [reason, description, dependencies, priority, filename, filepath]
70
70
  properties:
71
71
  reason: { type: string }
72
72
  description: { type: string }
73
73
  dependencies: { type: array, items: { type: string } }
74
74
  priority: { type: integer, minimum: 1 }
75
75
  filename: { type: string }
76
+ filepath: { type: string }
76
77
  tags: { type: array, items: { type: string } }
77
78
  interface:
78
79
  type: object
@@ -83,8 +84,30 @@ output_schema:
83
84
  type: object
84
85
  properties:
85
86
  route: { type: string }
86
- params: { type: array, items: { type: object } }
87
- dataSources: { type: array, items: { type: object } }
87
+ params:
88
+ type: array
89
+ items:
90
+ type: object
91
+ required: [name, type]
92
+ properties:
93
+ name: { type: string }
94
+ type: { type: string }
95
+ description: { type: string }
96
+ dataSources:
97
+ type: array
98
+ items:
99
+ type: object
100
+ required: [kind, source]
101
+ properties:
102
+ kind: { enum: [api, query, stream, file, cache, message, job, other] }
103
+ source: { type: string }
104
+ method: { type: string }
105
+ description: { type: string }
106
+ auth: { type: string }
107
+ inputs: { type: array, items: { type: string } }
108
+ outputs: { type: array, items: { type: string } }
109
+ refreshInterval: { type: string }
110
+ notes: { type: string }
88
111
  layout: { type: object }
89
112
  module: { type: object }
90
113
  api: { type: object }
@@ -107,8 +130,9 @@ INSTRUCTIONS:
107
130
  - Use only the facts from the included documents and files. Do not invent technologies or filenames.
108
131
  - If TECH_STACK_FILE is absent, infer a reasonable tech stack from the PRD and included files; state key assumptions within each item's description.
109
132
  - Output a single top-level JSON array of items. Each item must include:
110
- - reason, description, dependencies (filenames), priority (1 = highest), filename, optional tags.
133
+ - reason (briefly explain why this code module needs to exist), description, dependencies (filenames), priority (1 = highest), filename, filepath, optional tags.
111
134
  - interface: include only the applicable sub-object (component, page, module, api, graphql, cli, job, message, or config). Omit all non-applicable sub-objects entirely.
135
+ - When interface.type is "page", each entry in `dataSources` must be an object with at least `kind` (e.g., api/query) and `source` (e.g., URL or identifier). Provide `method`, `description`, and any other useful metadata when known.
112
136
  - Valid JSON only. No comments or trailing commas.
113
137
 
114
138
  OUTPUT FORMAT (authoritative):
@@ -117,20 +141,38 @@ OUTPUT FORMAT (authoritative):
117
141
  "type": "array",
118
142
  "items": {
119
143
  "type": "object",
120
- "required": ["reason", "description", "dependencies", "priority", "filename"],
144
+ "required": ["reason", "description", "dependencies", "priority", "filename", "filepath"],
121
145
  "properties": {
122
146
  "reason": {"type": "string"},
123
147
  "description": {"type": "string"},
124
148
  "dependencies": {"type": "array", "items": {"type": "string"}},
125
149
  "priority": {"type": "integer", "minimum": 1},
126
150
  "filename": {"type": "string"},
151
+ "filepath": {"type": "string"},
127
152
  "tags": {"type": "array", "items": {"type": "string"}},
128
153
  "interface": {
129
154
  "type": "object",
130
155
  "properties": {
131
156
  "type": {"enum": ["component", "page", "module", "api", "graphql", "cli", "job", "message", "config"]},
132
157
  "component": {"type": "object"},
133
- "page": {"type": "object", "properties": {"route": {"type": "string"}}},
158
+ "page": {
159
+ "type": "object",
160
+ "properties": {
161
+ "route": {"type": "string"},
162
+ "params": {
163
+ "type": "array",
164
+ "items": {
165
+ "type": "object",
166
+ "required": ["name", "type"],
167
+ "properties": {
168
+ "name": {"type": "string"},
169
+ "type": {"type": "string"},
170
+ "description": {"type": "string"}
171
+ }
172
+ }
173
+ }
174
+ }
175
+ },
134
176
  "module": {"type": "object"},
135
177
  "api": {"type": "object"},
136
178
  "graphql": {"type": "object"},
@@ -146,7 +188,7 @@ OUTPUT FORMAT (authoritative):
146
188
  ```
147
189
 
148
190
  INTERFACE TYPES (emit only applicable):
149
- - page: route (string), params? (array), dataSources? (array), layout? (object)
191
+ - page: route (string), params? (array of {name, type, description?}), dataSources? (array), layout? (object)
150
192
  - component: props (array of {name, type, required?}), emits? (array), context? (array)
151
193
  - module: functions (array of {name, signature, returns?, errors?, sideEffects?})
152
194
  - api: endpoints (array of {method, path, auth?, requestSchema?, responseSchema?, errors?})
@@ -163,6 +205,18 @@ FILENAME CONVENTIONS:
163
205
  - Python backend: api_Python.prompt -> api.py; orders_Python.prompt -> orders.py
164
206
  - Choose descriptive <base> names (e.g., orders_page, orders_api) and keep names consistent across dependencies.
165
207
 
208
+ FILEPATH CONVENTIONS:
209
+ - The "filepath" field specifies the path of the output source file from the source tree root, using conventions appropriate for the language and framework.
210
+ - Examples (adapt to your stack):
211
+ - Next.js app router: app/orders/page.tsx, app/layout.tsx, app/api/orders/route.ts
212
+ - Next.js pages router: pages/orders.tsx, pages/api/orders.ts
213
+ - Python FastAPI: src/api.py, src/orders.py, src/models/order.py
214
+ - React components: src/components/OrderList.tsx, src/hooks/useOrders.ts
215
+ - Config files: .env.example, pyproject.toml, package.json
216
+ - Use forward slashes (/) for path separators regardless of OS.
217
+ - Include the appropriate file extension for the target language (.tsx, .py, .rs, .go, etc.).
218
+ - Follow standard directory structures for the framework (e.g., app/ for Next.js 13+, src/ for typical React/Python projects).
219
+
166
220
  DEPENDENCY RULES:
167
221
  - The "dependencies" array must list other items by their prompt filenames (the "filename" values), not code filenames.
168
222
  - Do not reference files that are not part of this array unless they were explicitly provided via INCLUDE_FILES/DOC_FILES.
@@ -22,11 +22,11 @@ variables:
22
22
  type: string
23
23
  description: System layer or interface type for context.
24
24
  examples: [backend, frontend, api, graphql, cli, job, message, config, module, component, page]
25
- README_FILE:
25
+ PRD_FILE:
26
26
  required: false
27
27
  type: path
28
- description: Project README to provide overall context.
29
- example_paths: [README.md, docs/README.md]
28
+ description: Product requirements document providing overall context.
29
+ example_paths: [PRD.md, docs/product/prd.md]
30
30
  API_DOC_FILE:
31
31
  required: false
32
32
  type: path
@@ -48,7 +48,7 @@ variables:
48
48
  description: CSV of function inputs/outputs and dependencies for backend modules.
49
49
  example_paths: [prompts/backend/io_dependencies.csv]
50
50
  ARCHITECTURE_FILE:
51
- required: false
51
+ required: true
52
52
  type: path
53
53
  description: Architecture JSON (from architecture/architecture_json) to drive module scope, dependencies, and interface.
54
54
  example_paths: [architecture.json]
@@ -75,14 +75,14 @@ variables:
75
75
  default: py
76
76
  usage:
77
77
  generate:
78
- - name: Minimal (module only)
79
- command: pdd generate -e MODULE=orders -e LANG_OR_FRAMEWORK=Python --output 'prompts/${MODULE}_${LANG_OR_FRAMEWORK}.prompt' pdd/templates/generic/generate_prompt.prompt
78
+ - name: Minimal (architecture only)
79
+ command: pdd generate -e MODULE=orders -e LANG_OR_FRAMEWORK=Python -e ARCHITECTURE_FILE=architecture.json --output 'prompts/${MODULE}_${LANG_OR_FRAMEWORK}.prompt' pdd/templates/generic/generate_prompt.prompt
80
80
  - name: With project docs
81
- command: pdd generate -e MODULE=orders -e LANG_OR_FRAMEWORK=Python -e README_FILE=README.md -e API_DOC_FILE=docs/api-documentation.md -e DB_SCHEMA_FILE=context/database-schema.md --output 'prompts/${MODULE}_${LANG_OR_FRAMEWORK}.prompt' pdd/templates/generic/generate_prompt.prompt
81
+ command: pdd generate -e MODULE=orders -e LANG_OR_FRAMEWORK=Python -e ARCHITECTURE_FILE=architecture.json -e PRD_FILE=docs/PRD.md -e API_DOC_FILE=docs/api-documentation.md -e DB_SCHEMA_FILE=context/database-schema.md --output 'prompts/${MODULE}_${LANG_OR_FRAMEWORK}.prompt' pdd/templates/generic/generate_prompt.prompt
82
82
  - name: With CSVs and references (backend/Python)
83
- command: pdd generate -e MODULE=orders -e LANG_OR_FRAMEWORK=Python -e README_FILE=README.md -e API_DOC_FILE=docs/api-documentation.md -e DB_SCHEMA_FILE=context/database-schema.md -e BACKEND_FILES_CSV=prompts/backend/python_architecture.csv -e IO_DEPENDENCIES_CSV=prompts/backend/io_dependencies.csv -e CODE_GENERATOR_PROMPT=prompts/code_generator_python.prompt --output 'prompts/${MODULE}_${LANG_OR_FRAMEWORK}.prompt' pdd/templates/generic/generate_prompt.prompt
83
+ command: pdd generate -e MODULE=orders -e LANG_OR_FRAMEWORK=Python -e ARCHITECTURE_FILE=architecture.json -e PRD_FILE=docs/PRD.md -e API_DOC_FILE=docs/api-documentation.md -e DB_SCHEMA_FILE=context/database-schema.md -e BACKEND_FILES_CSV=prompts/backend/python_architecture.csv -e IO_DEPENDENCIES_CSV=prompts/backend/io_dependencies.csv -e CODE_GENERATOR_PROMPT=prompts/code_generator_python.prompt --output 'prompts/${MODULE}_${LANG_OR_FRAMEWORK}.prompt' pdd/templates/generic/generate_prompt.prompt
84
84
  - name: Frontend (TypeScriptReact) variant
85
- command: pdd generate -e MODULE=profile_page -e LANG_OR_FRAMEWORK=TypeScriptReact -e LAYER=frontend -e README_FILE=README.md --output 'prompts/${MODULE}_${LANG_OR_FRAMEWORK}.prompt' pdd/templates/generic/generate_prompt.prompt
85
+ command: pdd generate -e MODULE=profile_page -e LANG_OR_FRAMEWORK=TypeScriptReact -e LAYER=frontend -e ARCHITECTURE_FILE=architecture.json -e PRD_FILE=docs/PRD.md --output 'prompts/${MODULE}_${LANG_OR_FRAMEWORK}.prompt' pdd/templates/generic/generate_prompt.prompt
86
86
  - name: From architecture.json
87
87
  command: pdd generate -e MODULE=orders_api -e LANG_OR_FRAMEWORK=Python -e LAYER=api -e ARCHITECTURE_FILE=architecture.json --output 'prompts/${MODULE}_${LANG_OR_FRAMEWORK}.prompt' pdd/templates/generic/generate_prompt.prompt
88
88
 
@@ -94,8 +94,10 @@ discover:
94
94
 
95
95
  % You are an expert prompt writer and software architect for PDD. Your goal is to write a high-quality prompt that will generate the code for the ${MODULE} module/component. The prompt you create will be used to produce a detailed implementation specification in a file named ${MODULE}_${LANG_OR_FRAMEWORK}.prompt, suitable for the specified stack and layer.
96
96
 
97
- % Project context (optional but recommended):
98
- <readme><include>${README_FILE}</include></readme>
97
+ IMPORTANT: Your reply MUST begin with `<prompt>` on the very first line and end with `</prompt>` on the final line. Do not include any text, whitespace, or code fences outside this block.
98
+
99
+ % Project context (architecture required, others optional):
100
+ <prd><include>${PRD_FILE}</include></prd>
99
101
  <api><include>${API_DOC_FILE}</include></api>
100
102
  <database><include>${DB_SCHEMA_FILE}</include></database>
101
103
  <backend_files_csv><include>${BACKEND_FILES_CSV}</include></backend_files_csv>
@@ -110,8 +112,9 @@ discover:
110
112
  % Do the following:
111
113
  - Explain concisely what you are going to do (create a prompt for the ${MODULE} module/component for the specified layer and stack).
112
114
  - Analyze any difficulties this prompt might encounter for ${MODULE} (e.g., data modeling, API or UI contracts, transactions, idempotency, auth, state management, error handling) and briefly state mitigation strategies tailored to the given LAYER and LANG_OR_FRAMEWORK.
113
- - If ARCHITECTURE_FILE is provided, identify the item that corresponds to this prompt by matching `filename` to `${MODULE}_${LANG_OR_FRAMEWORK}.prompt` (or best match by basename and layer). Use that item’s `reason`, `description`, `dependencies`, `interface`, and `tags` to shape the sections below.
115
+ - Use the ARCHITECTURE_FILE to identify the item that corresponds to this prompt by matching `filename` to `${MODULE}_${LANG_OR_FRAMEWORK}.prompt` (or best match by basename and layer). Use that item’s `reason`, `description`, `dependencies`, `interface`, and `tags` to shape the sections below.
114
116
  - Then create the prompt content for ${MODULE} inside XML tags named prompt, ensuring conventions fit the stack and layer.
117
+ - Ensure the final response consists solely of the `<prompt>...</prompt>` block; nothing else (including whitespace) may appear before `<prompt>` or after `</prompt>`.
115
118
 
116
119
  % The prompt you generate must follow this structure:
117
120
  1) First paragraph: describe the role and responsibility of the ${MODULE} module/component within the system (consider the LAYER if provided).
@@ -127,9 +130,9 @@ discover:
127
130
  </orders_service>
128
131
  - Prefer real example files available in the provided context (use <include-many> when listing multiple). If examples are not provided, assume dependency examples live under context/ using the pattern context/[dependency_name]_example.${DEP_EXAMPLE_EXT}.
129
132
  - Include all necessary dependencies for the module/component (based on the provided context and references).
130
- - When using ARCHITECTURE_FILE, its `dependencies` reference other prompt filenames. Convert each dependency prompt filename into a sensible dependency name (strip language suffix and `_prompt`), and map to context files with the `${DEP_EXAMPLE_EXT}` extension if present; otherwise, list the prompt filename explicitly in a "Prompt Dependencies" subsection.
133
+ - The ARCHITECTURE_FILE lists `dependencies` referencing other prompt filenames. Convert each dependency prompt filename into a sensible dependency name (strip language suffix and `_prompt`), and map to context files with the `${DEP_EXAMPLE_EXT}` extension if present; otherwise, list the prompt filename explicitly in a "Prompt Dependencies" subsection.
131
134
 
132
- % Architecture awareness (when ARCHITECTURE_FILE provided):
135
+ % Architecture awareness (ARCHITECTURE_FILE is required):
133
136
  - Align the "Requirements" and "Instructions" with the selected item’s `interface.type` (e.g., page, component, module, api, graphql, cli, job, message, config).
134
137
  - For `api`, outline endpoints (method, path, auth) consistent with the architecture description; for `page`/`component`, describe route/props/data sources; for `job`, include trigger and retry policy; for `config`, list keys and sources.
135
138
 
@@ -139,4 +142,33 @@ discover:
139
142
  - Do not invent technologies or files; rely on the included context. If assumptions are necessary, state them explicitly and conservatively.
140
143
 
141
144
  % Output contract:
142
- - Return free-form text containing a single <prompt>...</prompt> XML section with the complete prompt content described above. Do not include additional commentary after the <prompt> block.
145
+ - Start the output with `<prompt>` on its own line and end with `</prompt>` on its own line.
146
+ - Do not emit any characters (including whitespace, markdown fences, or commentary) outside the `<prompt>...</prompt>` block.
147
+ - Within the tags, include the sections described above as plain text.
148
+ - OUTPUT FORMAT (authoritative – copy/paste and replace the bracketed placeholders, keeping every literal token):
149
+ ```text
150
+ <prompt>
151
+ {ROLE_PARAGRAPH}
152
+ Requirements
153
+ 1. {REQ_ITEM_1}
154
+ 2. {REQ_ITEM_2}
155
+ Dependencies
156
+ <{DEPENDENCY_TAG_1}>
157
+ <include>{DEPENDENCY_INCLUDE_1}</include>
158
+ </{DEPENDENCY_TAG_1}>
159
+ {OPTIONAL_ADDITIONAL_DEPENDENCY_TAGS}
160
+ Prompt Dependencies:
161
+ {PROMPT_DEPENDENCIES_SECTION}
162
+ Instructions
163
+ - {INSTRUCTION_1}
164
+ - {INSTRUCTION_2}
165
+ Deliverable
166
+ - {DELIVERABLE_1}
167
+ - {DELIVERABLE_2}
168
+ Implementation assumptions (explicit)
169
+ - {ASSUMPTION_1}
170
+ - {ASSUMPTION_2}
171
+ Please produce production-ready prompt content that will generate the module consistent with the above.
172
+ </prompt>
173
+ ```
174
+ Replace each `{PLACEHOLDER}` with concrete content while preserving the surrounding structure and literal `<prompt>` / `<include>` tags.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdd-cli
3
- Version: 0.0.61
3
+ Version: 0.0.63
4
4
  Summary: PDD (Prompt-Driven Development) Command Line Interface
5
5
  Author: Greg Tanaka
6
6
  Author-email: glt@alumni.caltech.edu
@@ -53,7 +53,7 @@ Requires-Dist: build; extra == "dev"
53
53
  Requires-Dist: twine; extra == "dev"
54
54
  Dynamic: license-file
55
55
 
56
- .. image:: https://img.shields.io/badge/pdd--cli-v0.0.61-blue
56
+ .. image:: https://img.shields.io/badge/pdd--cli-v0.0.63-blue
57
57
  :alt: PDD-CLI Version
58
58
 
59
59
  .. image:: https://img.shields.io/badge/Discord-join%20chat-7289DA.svg?logo=discord&logoColor=white&link=https://discord.gg/Yp4RTh8bG7
@@ -130,7 +130,7 @@ After installation, verify:
130
130
 
131
131
  pdd --version
132
132
 
133
- You'll see the current PDD version (e.g., 0.0.61).
133
+ You'll see the current PDD version (e.g., 0.0.63).
134
134
 
135
135
  Getting Started with Examples
136
136
  -----------------------------
@@ -1,4 +1,4 @@
1
- pdd/__init__.py,sha256=60zr1ZNOzlSl4emQ4nH962OEwIZiUFC4jsFk1CrMMHc,633
1
+ pdd/__init__.py,sha256=poOT3ybYXYnjrM8EcduTkCl3sMnj5dXCF_LBZI3jQB8,633
2
2
  pdd/auto_deps_main.py,sha256=cpP3bbzVL3jomrGinpzTxzIDIC8tmDDYOwUAC1TKRaw,3970
3
3
  pdd/auto_include.py,sha256=OJcdcwTwJNqHPHKG9P4m9Ij-PiLex0EbuwJP0uiQi_Y,7484
4
4
  pdd/auto_update.py,sha256=w6jzTnMiYRNpwQHQxWNiIAwQ0d6xh1iOB3xgDsabWtc,5236
@@ -6,7 +6,7 @@ pdd/bug_main.py,sha256=EtaGTuucQ7VgqOhyg4o6GFG7_QtTsDPTrRdGJWT648M,4841
6
6
  pdd/bug_to_unit_test.py,sha256=BoQqNyKQpBQDW8-JwBH_RX4RHRSiU8Kk3EplFrkECt0,6665
7
7
  pdd/change.py,sha256=Hg_x0pa370-e6oDiczaTgFAy3Am9ReCPkqFrvqv4U38,6114
8
8
  pdd/change_main.py,sha256=04VHiO_D-jlfeRn6rrVH7ZTA5agXPoJGm1StGI8--XY,27804
9
- pdd/cli.py,sha256=phCEbNXjK-3Orjg7N-yhKb5DeXAhX9s1q7sWpqPlDps,55747
9
+ pdd/cli.py,sha256=qjDBwwwE-sTWFqKTJOIiYh2nuimlTTgXtMDE0RUuVaU,60805
10
10
  pdd/cmd_test_main.py,sha256=M-i5x26ORXurt_pu8x1sgLAyVIItbuRThiux4wBg3Ls,7768
11
11
  pdd/code_generator.py,sha256=AxMRZKGIlLh9xWdn2FA6b3zSoZ-5TIZNIAzqjFboAQs,4718
12
12
  pdd/code_generator_main.py,sha256=UtoskalEPpMAvCO-zd6xmr1lbQqSWQ7BvYgNJCybqok,35151
@@ -50,7 +50,7 @@ pdd/pdd_completion.sh,sha256=xgx-g6aeCCrlh6loeLyJN5jCsX15YXrWyT1U499p3C0,6490
50
50
  pdd/pdd_completion.zsh,sha256=V9-V8jqw3osjlXNOvjYMJf0E771-_EQe-Cboo1xzPvY,17090
51
51
  pdd/postprocess.py,sha256=mNw3iSDxE-eTYo3QwJCj_EmdEnnB5ysUN62YPapC_IM,4433
52
52
  pdd/postprocess_0.py,sha256=OW17GyCFLYErCyWh2tL4syuho3q2yFf2wyekQ4BLdPM,2168
53
- pdd/preprocess.py,sha256=75-J1smdi1Uq7gRQRLtVdkIfwltkeIvIZE-TkxxxCz0,12326
53
+ pdd/preprocess.py,sha256=tmZiYlpiJHFDPuwlYtl1htQ7ZA77roGdPRvO4sHXYGU,18162
54
54
  pdd/preprocess_main.py,sha256=WGhOB9qEu7MmFoyXNml_AmqGii73LJWngx4kTlZ526k,3262
55
55
  pdd/process_csv_change.py,sha256=ckNqVPRooWVyIvmqjdEgo2PDLnpoQ6Taa2dUaWGRlzU,27926
56
56
  pdd/pytest_output.py,sha256=IrRKYneW_F6zv9WaJwKFGnOBLFBFjk1CnhO_EVAjb9E,6612
@@ -72,8 +72,8 @@ pdd/update_main.py,sha256=SWCd7Us3YatrDR7B66dQCpRCIgQoMHysPzxa4dedVmk,4385
72
72
  pdd/update_model_costs.py,sha256=RfeOlAHtc1FCx47A7CjrH2t5WXQclQ_9uYtNjtQh75I,22998
73
73
  pdd/update_prompt.py,sha256=zc-HiI1cwGBkJHVmNDyoSZa13lZH90VdB9l8ajdj6Kk,4543
74
74
  pdd/xml_tagger.py,sha256=5Bc3HRm7iz_XjBdzQIcMb8KocUQ8PELI2NN5Gw4amd4,4825
75
- pdd/data/language_format.csv,sha256=shimgYTHMJtfKQ1wpjjLto27TaMKU4OzNJ4hLeoXHms,957
76
- pdd/data/llm_model.csv,sha256=UxllgS0btSpCKpPgPnaTFAtZsAynBhLeZyoIVo0Tpwc,1698
75
+ pdd/data/language_format.csv,sha256=i4AfibdhmMnx_xAnv5jHA8TGSftjOJnLcKE53kS7kLY,1010
76
+ pdd/data/llm_model.csv,sha256=u7naNW110fejsV443qlzs0_TmCAzxa8EJogjmmJSAZs,1702
77
77
  pdd/prompts/auto_include_LLM.prompt,sha256=sNF2rdJu9wJ8c0lwjCfZ9ZReX8zGXRUNehRs1ZiyDoc,12108
78
78
  pdd/prompts/bug_to_unit_test_LLM.prompt,sha256=KdMkvRVnjVSf0NTYIaDXIMT93xPttXEwkMpjWx5leLs,1588
79
79
  pdd/prompts/change_LLM.prompt,sha256=5rgWIL16p3VRURd2_lNtcbu_MVRqPhI8gFIBt1gkzDQ,2164
@@ -110,11 +110,11 @@ pdd/prompts/trim_results_start_LLM.prompt,sha256=OKz8fAf1cYWKWgslFOHEkUpfaUDARh3
110
110
  pdd/prompts/unfinished_prompt_LLM.prompt,sha256=vud_G9PlVv9Ig64uBC-hPEVFRk5lwpc8pW6tOIxJM4I,5082
111
111
  pdd/prompts/update_prompt_LLM.prompt,sha256=prIc8uLp2jqnLTHt6JvWDZGanPZipivhhYeXe0lVaYw,1328
112
112
  pdd/prompts/xml_convertor_LLM.prompt,sha256=YGRGXJeg6EhM9690f-SKqQrKqSJjLFD51UrPOlO0Frg,2786
113
- pdd/templates/architecture/architecture_json.prompt,sha256=uSNSsKTL-cuMMhi5a4GSpC94DKkOFAlXh7R0CUlo-hg,8126
114
- pdd/templates/generic/generate_prompt.prompt,sha256=EIE4vCEauJglLxS8OxuMx1S4JnPexi-yXxEOpIwaRW4,9276
115
- pdd_cli-0.0.61.dist-info/licenses/LICENSE,sha256=kvTJnnxPVTYlGKSY4ZN1kzdmJ0lxRdNWxgupaB27zsU,1066
116
- pdd_cli-0.0.61.dist-info/METADATA,sha256=iS6Mds35DEHVnnWEfrKI0tDsInfBj7V49NUFd8UWhdI,12687
117
- pdd_cli-0.0.61.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
118
- pdd_cli-0.0.61.dist-info/entry_points.txt,sha256=Kr8HtNVb8uHZtQJNH4DnF8j7WNgWQbb7_Pw5hECSR-I,36
119
- pdd_cli-0.0.61.dist-info/top_level.txt,sha256=xjnhIACeMcMeDfVNREgQZl4EbTni2T11QkL5r7E-sbE,4
120
- pdd_cli-0.0.61.dist-info/RECORD,,
113
+ pdd/templates/architecture/architecture_json.prompt,sha256=lmEM6f1EGK73wivONssvlSNXuTy2nYv-p-oRqBg1iFg,10745
114
+ pdd/templates/generic/generate_prompt.prompt,sha256=4PhcNczpYpwSiaGt0r2f-vhSO3JFqeU1fTEy6YpPudQ,10758
115
+ pdd_cli-0.0.63.dist-info/licenses/LICENSE,sha256=kvTJnnxPVTYlGKSY4ZN1kzdmJ0lxRdNWxgupaB27zsU,1066
116
+ pdd_cli-0.0.63.dist-info/METADATA,sha256=LtF3JdpNk8hnTDvVoNhJzqdoOMINHkdVM9Luxda6sV4,12687
117
+ pdd_cli-0.0.63.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
118
+ pdd_cli-0.0.63.dist-info/entry_points.txt,sha256=Kr8HtNVb8uHZtQJNH4DnF8j7WNgWQbb7_Pw5hECSR-I,36
119
+ pdd_cli-0.0.63.dist-info/top_level.txt,sha256=xjnhIACeMcMeDfVNREgQZl4EbTni2T11QkL5r7E-sbE,4
120
+ pdd_cli-0.0.63.dist-info/RECORD,,