pdd-cli 0.0.55__py3-none-any.whl → 0.0.56__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 +1 -1
- pdd/auto_deps_main.py +3 -2
- pdd/bug_main.py +3 -2
- pdd/change_main.py +1 -0
- pdd/cli.py +44 -2
- pdd/cmd_test_main.py +1 -0
- pdd/code_generator_main.py +1 -0
- pdd/conflicts_main.py +3 -2
- pdd/construct_paths.py +17 -0
- pdd/context_generator_main.py +2 -1
- pdd/crash_main.py +3 -2
- pdd/data/language_format.csv +2 -1
- pdd/detect_change_main.py +3 -2
- pdd/fix_main.py +3 -2
- pdd/fix_verification_main.py +1 -0
- pdd/preprocess_main.py +2 -1
- pdd/split_main.py +3 -2
- pdd/sync_determine_operation.py +28 -15
- pdd/sync_main.py +3 -1
- pdd/sync_orchestration.py +3 -2
- pdd/trace_main.py +2 -1
- pdd/update_main.py +2 -1
- {pdd_cli-0.0.55.dist-info → pdd_cli-0.0.56.dist-info}/METADATA +3 -3
- {pdd_cli-0.0.55.dist-info → pdd_cli-0.0.56.dist-info}/RECORD +28 -28
- {pdd_cli-0.0.55.dist-info → pdd_cli-0.0.56.dist-info}/WHEEL +0 -0
- {pdd_cli-0.0.55.dist-info → pdd_cli-0.0.56.dist-info}/entry_points.txt +0 -0
- {pdd_cli-0.0.55.dist-info → pdd_cli-0.0.56.dist-info}/licenses/LICENSE +0 -0
- {pdd_cli-0.0.55.dist-info → pdd_cli-0.0.56.dist-info}/top_level.txt +0 -0
pdd/__init__.py
CHANGED
pdd/auto_deps_main.py
CHANGED
|
@@ -49,7 +49,8 @@ def auto_deps_main( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
49
49
|
force=ctx.obj.get('force', False),
|
|
50
50
|
quiet=ctx.obj.get('quiet', False),
|
|
51
51
|
command="auto-deps",
|
|
52
|
-
command_options=command_options
|
|
52
|
+
command_options=command_options,
|
|
53
|
+
context_override=ctx.obj.get('context')
|
|
53
54
|
)
|
|
54
55
|
|
|
55
56
|
# Get the CSV file path
|
|
@@ -101,4 +102,4 @@ def auto_deps_main( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
101
102
|
except Exception as exc:
|
|
102
103
|
if not ctx.obj.get('quiet', False):
|
|
103
104
|
rprint(f"[bold red]Error:[/bold red] {str(exc)}")
|
|
104
|
-
sys.exit(1)
|
|
105
|
+
sys.exit(1)
|
pdd/bug_main.py
CHANGED
|
@@ -50,7 +50,8 @@ def bug_main(
|
|
|
50
50
|
force=ctx.obj.get('force', False),
|
|
51
51
|
quiet=ctx.obj.get('quiet', False),
|
|
52
52
|
command="bug",
|
|
53
|
-
command_options=command_options
|
|
53
|
+
command_options=command_options,
|
|
54
|
+
context_override=ctx.obj.get('context')
|
|
54
55
|
)
|
|
55
56
|
|
|
56
57
|
# Use the language detected by construct_paths if none was explicitly provided
|
|
@@ -117,4 +118,4 @@ def bug_main(
|
|
|
117
118
|
except Exception as e:
|
|
118
119
|
if not ctx.obj.get('quiet', False):
|
|
119
120
|
rprint(f"[bold red]Error:[/bold red] {str(e)}")
|
|
120
|
-
sys.exit(1)
|
|
121
|
+
sys.exit(1)
|
pdd/change_main.py
CHANGED
|
@@ -203,6 +203,7 @@ def change_main(
|
|
|
203
203
|
quiet=quiet,
|
|
204
204
|
command="change",
|
|
205
205
|
command_options=command_options,
|
|
206
|
+
context_override=ctx.obj.get('context')
|
|
206
207
|
)
|
|
207
208
|
logger.debug("construct_paths returned:")
|
|
208
209
|
logger.debug(" input_strings keys: %s", list(input_strings.keys()))
|
pdd/cli.py
CHANGED
|
@@ -26,7 +26,7 @@ from .cmd_test_main import cmd_test_main
|
|
|
26
26
|
from .code_generator_main import code_generator_main
|
|
27
27
|
from .conflicts_main import conflicts_main
|
|
28
28
|
# Need to import construct_paths for tests patching pdd.cli.construct_paths
|
|
29
|
-
from .construct_paths import construct_paths
|
|
29
|
+
from .construct_paths import construct_paths, list_available_contexts
|
|
30
30
|
from .context_generator_main import context_generator_main
|
|
31
31
|
from .crash_main import crash_main
|
|
32
32
|
from .detect_change_main import detect_change_main
|
|
@@ -76,7 +76,7 @@ def handle_error(exception: Exception, command_name: str, quiet: bool):
|
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
# --- Main CLI Group ---
|
|
79
|
-
@click.group(chain=True, help="PDD (Prompt-Driven Development) Command Line Interface.")
|
|
79
|
+
@click.group(chain=True, invoke_without_command=True, help="PDD (Prompt-Driven Development) Command Line Interface.")
|
|
80
80
|
@click.option(
|
|
81
81
|
"--force",
|
|
82
82
|
is_flag=True,
|
|
@@ -134,6 +134,20 @@ def handle_error(exception: Exception, command_name: str, quiet: bool):
|
|
|
134
134
|
default=False,
|
|
135
135
|
help="Run commands locally instead of in the cloud.",
|
|
136
136
|
)
|
|
137
|
+
@click.option(
|
|
138
|
+
"--context",
|
|
139
|
+
"context_override",
|
|
140
|
+
type=str,
|
|
141
|
+
default=None,
|
|
142
|
+
help="Override automatic context detection and use the specified .pddrc context.",
|
|
143
|
+
)
|
|
144
|
+
@click.option(
|
|
145
|
+
"--list-contexts",
|
|
146
|
+
"list_contexts",
|
|
147
|
+
is_flag=True,
|
|
148
|
+
default=False,
|
|
149
|
+
help="List available contexts from .pddrc and exit.",
|
|
150
|
+
)
|
|
137
151
|
@click.version_option(version=__version__, package_name="pdd-cli")
|
|
138
152
|
@click.pass_context
|
|
139
153
|
def cli(
|
|
@@ -147,6 +161,8 @@ def cli(
|
|
|
147
161
|
review_examples: bool,
|
|
148
162
|
local: bool,
|
|
149
163
|
time: Optional[float], # Type hint is Optional[float]
|
|
164
|
+
context_override: Optional[str],
|
|
165
|
+
list_contexts: bool,
|
|
150
166
|
):
|
|
151
167
|
"""
|
|
152
168
|
Main entry point for the PDD CLI. Handles global options and initializes context.
|
|
@@ -166,11 +182,37 @@ def cli(
|
|
|
166
182
|
ctx.obj["local"] = local
|
|
167
183
|
# Use DEFAULT_TIME if time is not provided
|
|
168
184
|
ctx.obj["time"] = time if time is not None else DEFAULT_TIME
|
|
185
|
+
# Persist context override for downstream calls
|
|
186
|
+
ctx.obj["context"] = context_override
|
|
169
187
|
|
|
170
188
|
# Suppress verbose if quiet is enabled
|
|
171
189
|
if quiet:
|
|
172
190
|
ctx.obj["verbose"] = False
|
|
173
191
|
|
|
192
|
+
# If --list-contexts is provided, print and exit before any other actions
|
|
193
|
+
if list_contexts:
|
|
194
|
+
try:
|
|
195
|
+
names = list_available_contexts()
|
|
196
|
+
except Exception as exc:
|
|
197
|
+
# Surface config errors as usage errors
|
|
198
|
+
raise click.UsageError(f"Failed to load .pddrc: {exc}")
|
|
199
|
+
# Print one per line; avoid Rich formatting for portability
|
|
200
|
+
for name in names:
|
|
201
|
+
click.echo(name)
|
|
202
|
+
ctx.exit(0)
|
|
203
|
+
|
|
204
|
+
# Optional early validation for --context
|
|
205
|
+
if context_override:
|
|
206
|
+
try:
|
|
207
|
+
names = list_available_contexts()
|
|
208
|
+
except Exception as exc:
|
|
209
|
+
# If .pddrc is malformed, propagate as usage error
|
|
210
|
+
raise click.UsageError(f"Failed to load .pddrc: {exc}")
|
|
211
|
+
if context_override not in names:
|
|
212
|
+
raise click.UsageError(
|
|
213
|
+
f"Unknown context '{context_override}'. Available contexts: {', '.join(names)}"
|
|
214
|
+
)
|
|
215
|
+
|
|
174
216
|
# Perform auto-update check unless disabled
|
|
175
217
|
if os.getenv("PDD_AUTO_UPDATE", "true").lower() != "false":
|
|
176
218
|
try:
|
pdd/cmd_test_main.py
CHANGED
pdd/code_generator_main.py
CHANGED
|
@@ -184,6 +184,7 @@ def code_generator_main(
|
|
|
184
184
|
quiet=quiet,
|
|
185
185
|
command="generate",
|
|
186
186
|
command_options=command_options,
|
|
187
|
+
context_override=ctx.obj.get('context')
|
|
187
188
|
)
|
|
188
189
|
prompt_content = input_strings["prompt_file"]
|
|
189
190
|
# Determine final output path: if user passed a directory, use resolved file path
|
pdd/conflicts_main.py
CHANGED
|
@@ -33,7 +33,8 @@ def conflicts_main(ctx: click.Context, prompt1: str, prompt2: str, output: Optio
|
|
|
33
33
|
force=ctx.obj.get('force', False),
|
|
34
34
|
quiet=ctx.obj.get('quiet', False),
|
|
35
35
|
command="conflicts",
|
|
36
|
-
command_options=command_options
|
|
36
|
+
command_options=command_options,
|
|
37
|
+
context_override=ctx.obj.get('context')
|
|
37
38
|
)
|
|
38
39
|
|
|
39
40
|
# Load input files
|
|
@@ -91,4 +92,4 @@ def conflicts_main(ctx: click.Context, prompt1: str, prompt2: str, output: Optio
|
|
|
91
92
|
except Exception as e:
|
|
92
93
|
if not ctx.obj.get('quiet', False):
|
|
93
94
|
rprint(f"[bold red]Error:[/bold red] {str(e)}")
|
|
94
|
-
sys.exit(1)
|
|
95
|
+
sys.exit(1)
|
pdd/construct_paths.py
CHANGED
|
@@ -56,6 +56,23 @@ def _load_pddrc_config(pddrc_path: Path) -> Dict[str, Any]:
|
|
|
56
56
|
except Exception as e:
|
|
57
57
|
raise ValueError(f"Error loading .pddrc: {e}")
|
|
58
58
|
|
|
59
|
+
def list_available_contexts(start_path: Optional[Path] = None) -> list[str]:
|
|
60
|
+
"""Return sorted context names from the nearest .pddrc.
|
|
61
|
+
|
|
62
|
+
- Searches upward from `start_path` (or CWD) for a `.pddrc` file.
|
|
63
|
+
- If found, loads and validates it, then returns sorted context names.
|
|
64
|
+
- If no `.pddrc` exists, returns ["default"].
|
|
65
|
+
- Propagates ValueError for malformed `.pddrc` to allow callers to render
|
|
66
|
+
helpful errors.
|
|
67
|
+
"""
|
|
68
|
+
pddrc = _find_pddrc_file(start_path)
|
|
69
|
+
if not pddrc:
|
|
70
|
+
return ["default"]
|
|
71
|
+
config = _load_pddrc_config(pddrc)
|
|
72
|
+
contexts = config.get("contexts", {})
|
|
73
|
+
names = sorted(contexts.keys()) if isinstance(contexts, dict) else []
|
|
74
|
+
return names or ["default"]
|
|
75
|
+
|
|
59
76
|
def _detect_context(current_dir: Path, config: Dict[str, Any], context_override: Optional[str] = None) -> Optional[str]:
|
|
60
77
|
"""Detect the appropriate context based on current directory path."""
|
|
61
78
|
if context_override:
|
pdd/context_generator_main.py
CHANGED
|
@@ -31,7 +31,8 @@ def context_generator_main(ctx: click.Context, prompt_file: str, code_file: str,
|
|
|
31
31
|
force=ctx.obj.get('force', False),
|
|
32
32
|
quiet=ctx.obj.get('quiet', False),
|
|
33
33
|
command="example",
|
|
34
|
-
command_options=command_options
|
|
34
|
+
command_options=command_options,
|
|
35
|
+
context_override=ctx.obj.get('context')
|
|
35
36
|
)
|
|
36
37
|
|
|
37
38
|
# Load input files
|
pdd/crash_main.py
CHANGED
|
@@ -77,7 +77,8 @@ def crash_main(
|
|
|
77
77
|
force=force,
|
|
78
78
|
quiet=quiet,
|
|
79
79
|
command="crash",
|
|
80
|
-
command_options=command_options
|
|
80
|
+
command_options=command_options,
|
|
81
|
+
context_override=ctx.obj.get('context')
|
|
81
82
|
)
|
|
82
83
|
|
|
83
84
|
prompt_content = input_strings["prompt_file"]
|
|
@@ -177,4 +178,4 @@ def crash_main(
|
|
|
177
178
|
except Exception as e:
|
|
178
179
|
if not quiet:
|
|
179
180
|
rprint(f"[bold red]An unexpected error occurred:[/bold red] {str(e)}")
|
|
180
|
-
sys.exit(1)
|
|
181
|
+
sys.exit(1)
|
pdd/data/language_format.csv
CHANGED
pdd/detect_change_main.py
CHANGED
|
@@ -44,7 +44,8 @@ def detect_change_main(
|
|
|
44
44
|
force=ctx.obj.get('force', False),
|
|
45
45
|
quiet=ctx.obj.get('quiet', False),
|
|
46
46
|
command="detect",
|
|
47
|
-
command_options=command_options
|
|
47
|
+
command_options=command_options,
|
|
48
|
+
context_override=ctx.obj.get('context')
|
|
48
49
|
)
|
|
49
50
|
|
|
50
51
|
# Get change description content
|
|
@@ -100,4 +101,4 @@ def detect_change_main(
|
|
|
100
101
|
except Exception as e:
|
|
101
102
|
if not ctx.obj.get('quiet', False):
|
|
102
103
|
rprint(f"[bold red]Error:[/bold red] {str(e)}")
|
|
103
|
-
sys.exit(1)
|
|
104
|
+
sys.exit(1)
|
pdd/fix_main.py
CHANGED
|
@@ -97,7 +97,8 @@ def fix_main(
|
|
|
97
97
|
quiet=ctx.obj.get('quiet', False),
|
|
98
98
|
command="fix",
|
|
99
99
|
command_options=command_options,
|
|
100
|
-
create_error_file=loop # Only create error file if in loop mode
|
|
100
|
+
create_error_file=loop, # Only create error file if in loop mode
|
|
101
|
+
context_override=ctx.obj.get('context')
|
|
101
102
|
)
|
|
102
103
|
|
|
103
104
|
# Get parameters from context
|
|
@@ -296,4 +297,4 @@ def fix_main(
|
|
|
296
297
|
# Print other errors normally, escaping the error string
|
|
297
298
|
from rich.markup import escape # Ensure escape is imported
|
|
298
299
|
rprint(f"[bold red]Error:[/bold red] {escape(str(e))}")
|
|
299
|
-
sys.exit(1)
|
|
300
|
+
sys.exit(1)
|
pdd/fix_verification_main.py
CHANGED
|
@@ -204,6 +204,7 @@ def fix_verification_main(
|
|
|
204
204
|
quiet=quiet,
|
|
205
205
|
command="verify",
|
|
206
206
|
command_options=command_options,
|
|
207
|
+
context_override=ctx.obj.get('context')
|
|
207
208
|
)
|
|
208
209
|
output_code_path = output_file_paths.get("output_code")
|
|
209
210
|
output_results_path = output_file_paths.get("output_results")
|
pdd/preprocess_main.py
CHANGED
|
@@ -33,6 +33,7 @@ def preprocess_main(
|
|
|
33
33
|
quiet=ctx.obj.get("quiet", False),
|
|
34
34
|
command="preprocess",
|
|
35
35
|
command_options=command_options,
|
|
36
|
+
context_override=ctx.obj.get('context')
|
|
36
37
|
)
|
|
37
38
|
|
|
38
39
|
# Load prompt file
|
|
@@ -76,4 +77,4 @@ def preprocess_main(
|
|
|
76
77
|
except Exception as e:
|
|
77
78
|
if not ctx.obj.get("quiet", False):
|
|
78
79
|
rprint(f"[bold red]Error during preprocessing:[/bold red] {e}")
|
|
79
|
-
sys.exit(1)
|
|
80
|
+
sys.exit(1)
|
pdd/split_main.py
CHANGED
|
@@ -53,7 +53,8 @@ def split_main(
|
|
|
53
53
|
force=ctx.obj.get('force', False),
|
|
54
54
|
quiet=ctx.obj.get('quiet', False),
|
|
55
55
|
command="split",
|
|
56
|
-
command_options=command_options
|
|
56
|
+
command_options=command_options,
|
|
57
|
+
context_override=ctx.obj.get('context')
|
|
57
58
|
)
|
|
58
59
|
|
|
59
60
|
# Get parameters from context
|
|
@@ -113,4 +114,4 @@ def split_main(
|
|
|
113
114
|
elif isinstance(e, ValueError):
|
|
114
115
|
rprint("[yellow]Hint: Check if input files have valid content.[/yellow]")
|
|
115
116
|
|
|
116
|
-
sys.exit(1)
|
|
117
|
+
sys.exit(1)
|
pdd/sync_determine_operation.py
CHANGED
|
@@ -209,7 +209,7 @@ def get_extension(language: str) -> str:
|
|
|
209
209
|
return extensions.get(language.lower(), language.lower())
|
|
210
210
|
|
|
211
211
|
|
|
212
|
-
def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts") -> Dict[str, Path]:
|
|
212
|
+
def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts", context_override: Optional[str] = None) -> Dict[str, Path]:
|
|
213
213
|
"""Returns a dictionary mapping file types to their expected Path objects."""
|
|
214
214
|
import logging
|
|
215
215
|
logger = logging.getLogger(__name__)
|
|
@@ -233,7 +233,8 @@ def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts
|
|
|
233
233
|
force=True,
|
|
234
234
|
quiet=True,
|
|
235
235
|
command="sync",
|
|
236
|
-
command_options={"basename": basename, "language": language}
|
|
236
|
+
command_options={"basename": basename, "language": language},
|
|
237
|
+
context_override=context_override
|
|
237
238
|
)
|
|
238
239
|
|
|
239
240
|
import logging
|
|
@@ -299,7 +300,8 @@ def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts
|
|
|
299
300
|
force=True, # Use force=True to avoid interactive prompts during sync
|
|
300
301
|
quiet=True,
|
|
301
302
|
command="sync", # Use sync command to get more tolerant path handling
|
|
302
|
-
command_options={"basename": basename, "language": language}
|
|
303
|
+
command_options={"basename": basename, "language": language},
|
|
304
|
+
context_override=context_override
|
|
303
305
|
)
|
|
304
306
|
|
|
305
307
|
# For sync command, output_file_paths contains the configured paths
|
|
@@ -332,7 +334,8 @@ def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts
|
|
|
332
334
|
# Get example path using example command
|
|
333
335
|
_, _, example_output_paths, _ = construct_paths(
|
|
334
336
|
input_file_paths={"prompt_file": prompt_path, "code_file": code_path},
|
|
335
|
-
force=True, quiet=True, command="example", command_options={}
|
|
337
|
+
force=True, quiet=True, command="example", command_options={},
|
|
338
|
+
context_override=context_override
|
|
336
339
|
)
|
|
337
340
|
example_path = Path(example_output_paths.get('output', f"{basename}_example.{get_extension(language)}"))
|
|
338
341
|
|
|
@@ -340,7 +343,8 @@ def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts
|
|
|
340
343
|
try:
|
|
341
344
|
_, _, test_output_paths, _ = construct_paths(
|
|
342
345
|
input_file_paths={"prompt_file": prompt_path, "code_file": code_path},
|
|
343
|
-
force=True, quiet=True, command="test", command_options={}
|
|
346
|
+
force=True, quiet=True, command="test", command_options={},
|
|
347
|
+
context_override=context_override
|
|
344
348
|
)
|
|
345
349
|
test_path = Path(test_output_paths.get('output', f"test_{basename}.{get_extension(language)}"))
|
|
346
350
|
except FileNotFoundError:
|
|
@@ -365,14 +369,16 @@ def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts
|
|
|
365
369
|
# Get configured directories by using construct_paths with just the prompt file
|
|
366
370
|
_, _, example_output_paths, _ = construct_paths(
|
|
367
371
|
input_file_paths={"prompt_file": prompt_path},
|
|
368
|
-
force=True, quiet=True, command="example", command_options={}
|
|
372
|
+
force=True, quiet=True, command="example", command_options={},
|
|
373
|
+
context_override=context_override
|
|
369
374
|
)
|
|
370
375
|
example_path = Path(example_output_paths.get('output', f"{basename}_example.{get_extension(language)}"))
|
|
371
376
|
|
|
372
377
|
try:
|
|
373
378
|
_, _, test_output_paths, _ = construct_paths(
|
|
374
379
|
input_file_paths={"prompt_file": prompt_path},
|
|
375
|
-
force=True, quiet=True, command="test", command_options={}
|
|
380
|
+
force=True, quiet=True, command="test", command_options={},
|
|
381
|
+
context_override=context_override
|
|
376
382
|
)
|
|
377
383
|
test_path = Path(test_output_paths.get('output', f"test_{basename}.{get_extension(language)}"))
|
|
378
384
|
except Exception:
|
|
@@ -768,7 +774,7 @@ def _check_example_success_history(basename: str, language: str) -> bool:
|
|
|
768
774
|
return False
|
|
769
775
|
|
|
770
776
|
|
|
771
|
-
def sync_determine_operation(basename: str, language: str, target_coverage: float, budget: float = 10.0, log_mode: bool = False, prompts_dir: str = "prompts", skip_tests: bool = False, skip_verify: bool = False) -> SyncDecision:
|
|
777
|
+
def sync_determine_operation(basename: str, language: str, target_coverage: float, budget: float = 10.0, log_mode: bool = False, prompts_dir: str = "prompts", skip_tests: bool = False, skip_verify: bool = False, context_override: Optional[str] = None) -> SyncDecision:
|
|
772
778
|
"""
|
|
773
779
|
Core decision-making function for sync operations with skip flag awareness.
|
|
774
780
|
|
|
@@ -788,14 +794,14 @@ def sync_determine_operation(basename: str, language: str, target_coverage: floa
|
|
|
788
794
|
|
|
789
795
|
if log_mode:
|
|
790
796
|
# Skip locking for read-only analysis
|
|
791
|
-
return _perform_sync_analysis(basename, language, target_coverage, budget, prompts_dir, skip_tests, skip_verify)
|
|
797
|
+
return _perform_sync_analysis(basename, language, target_coverage, budget, prompts_dir, skip_tests, skip_verify, context_override)
|
|
792
798
|
else:
|
|
793
799
|
# Normal exclusive locking for actual operations
|
|
794
800
|
with SyncLock(basename, language) as lock:
|
|
795
|
-
return _perform_sync_analysis(basename, language, target_coverage, budget, prompts_dir, skip_tests, skip_verify)
|
|
801
|
+
return _perform_sync_analysis(basename, language, target_coverage, budget, prompts_dir, skip_tests, skip_verify, context_override)
|
|
796
802
|
|
|
797
803
|
|
|
798
|
-
def _perform_sync_analysis(basename: str, language: str, target_coverage: float, budget: float, prompts_dir: str = "prompts", skip_tests: bool = False, skip_verify: bool = False) -> SyncDecision:
|
|
804
|
+
def _perform_sync_analysis(basename: str, language: str, target_coverage: float, budget: float, prompts_dir: str = "prompts", skip_tests: bool = False, skip_verify: bool = False, context_override: Optional[str] = None) -> SyncDecision:
|
|
799
805
|
"""
|
|
800
806
|
Perform the sync state analysis without locking concerns.
|
|
801
807
|
|
|
@@ -846,7 +852,7 @@ def _perform_sync_analysis(basename: str, language: str, target_coverage: float,
|
|
|
846
852
|
# Check test failures (after crash verification check)
|
|
847
853
|
if run_report.tests_failed > 0:
|
|
848
854
|
# First check if the test file actually exists
|
|
849
|
-
pdd_files = get_pdd_file_paths(basename, language, prompts_dir)
|
|
855
|
+
pdd_files = get_pdd_file_paths(basename, language, prompts_dir, context_override=context_override)
|
|
850
856
|
test_file = pdd_files.get('test')
|
|
851
857
|
|
|
852
858
|
# Only suggest 'fix' if test file exists
|
|
@@ -945,7 +951,7 @@ def _perform_sync_analysis(basename: str, language: str, target_coverage: float,
|
|
|
945
951
|
)
|
|
946
952
|
|
|
947
953
|
# 2. Analyze File State
|
|
948
|
-
paths = get_pdd_file_paths(basename, language, prompts_dir)
|
|
954
|
+
paths = get_pdd_file_paths(basename, language, prompts_dir, context_override=context_override)
|
|
949
955
|
current_hashes = calculate_current_hashes(paths)
|
|
950
956
|
|
|
951
957
|
# 3. Implement the Decision Tree
|
|
@@ -1264,7 +1270,14 @@ def _perform_sync_analysis(basename: str, language: str, target_coverage: float,
|
|
|
1264
1270
|
)
|
|
1265
1271
|
|
|
1266
1272
|
|
|
1267
|
-
def analyze_conflict_with_llm(
|
|
1273
|
+
def analyze_conflict_with_llm(
|
|
1274
|
+
basename: str,
|
|
1275
|
+
language: str,
|
|
1276
|
+
fingerprint: Fingerprint,
|
|
1277
|
+
changed_files: List[str],
|
|
1278
|
+
prompts_dir: str = "prompts",
|
|
1279
|
+
context_override: Optional[str] = None,
|
|
1280
|
+
) -> SyncDecision:
|
|
1268
1281
|
"""
|
|
1269
1282
|
Resolve complex sync conflicts using an LLM.
|
|
1270
1283
|
|
|
@@ -1297,7 +1310,7 @@ def analyze_conflict_with_llm(basename: str, language: str, fingerprint: Fingerp
|
|
|
1297
1310
|
)
|
|
1298
1311
|
|
|
1299
1312
|
# 2. Gather file paths and diffs
|
|
1300
|
-
paths = get_pdd_file_paths(basename, language, prompts_dir)
|
|
1313
|
+
paths = get_pdd_file_paths(basename, language, prompts_dir, context_override=context_override)
|
|
1301
1314
|
|
|
1302
1315
|
# Generate diffs for changed files
|
|
1303
1316
|
diffs = {}
|
pdd/sync_main.py
CHANGED
|
@@ -192,6 +192,7 @@ def sync_main(
|
|
|
192
192
|
log=True,
|
|
193
193
|
verbose=verbose,
|
|
194
194
|
quiet=quiet,
|
|
195
|
+
context_override=context_override,
|
|
195
196
|
)
|
|
196
197
|
return {}, 0.0, ""
|
|
197
198
|
|
|
@@ -280,6 +281,7 @@ def sync_main(
|
|
|
280
281
|
review_examples=review_examples,
|
|
281
282
|
local=local,
|
|
282
283
|
context_config=resolved_config,
|
|
284
|
+
context_override=context_override,
|
|
283
285
|
)
|
|
284
286
|
|
|
285
287
|
lang_cost = sync_result.get("total_cost", 0.0)
|
|
@@ -330,4 +332,4 @@ def sync_main(
|
|
|
330
332
|
aggregated_results["total_cost"] = total_cost
|
|
331
333
|
aggregated_results["primary_model"] = primary_model
|
|
332
334
|
|
|
333
|
-
return aggregated_results, total_cost, primary_model
|
|
335
|
+
return aggregated_results, total_cost, primary_model
|
pdd/sync_orchestration.py
CHANGED
|
@@ -341,6 +341,7 @@ def sync_orchestration(
|
|
|
341
341
|
review_examples: bool = False,
|
|
342
342
|
local: bool = False,
|
|
343
343
|
context_config: Optional[Dict[str, str]] = None,
|
|
344
|
+
context_override: Optional[str] = None,
|
|
344
345
|
) -> Dict[str, Any]:
|
|
345
346
|
"""
|
|
346
347
|
Orchestrates the complete PDD sync workflow with parallel animation.
|
|
@@ -358,7 +359,7 @@ def sync_orchestration(
|
|
|
358
359
|
|
|
359
360
|
# --- Initialize State and Paths ---
|
|
360
361
|
try:
|
|
361
|
-
pdd_files = get_pdd_file_paths(basename, language, prompts_dir)
|
|
362
|
+
pdd_files = get_pdd_file_paths(basename, language, prompts_dir, context_override=context_override)
|
|
362
363
|
# Debug: Print the paths we got
|
|
363
364
|
print(f"DEBUG: get_pdd_file_paths returned:")
|
|
364
365
|
print(f" test: {pdd_files.get('test', 'N/A')}")
|
|
@@ -457,7 +458,7 @@ def sync_orchestration(
|
|
|
457
458
|
"percentage": (budget_remaining / budget) * 100
|
|
458
459
|
})
|
|
459
460
|
|
|
460
|
-
decision = sync_determine_operation(basename, language, target_coverage, budget_remaining, False, prompts_dir, skip_tests, skip_verify)
|
|
461
|
+
decision = sync_determine_operation(basename, language, target_coverage, budget_remaining, False, prompts_dir, skip_tests, skip_verify, context_override)
|
|
461
462
|
operation = decision.operation
|
|
462
463
|
|
|
463
464
|
# Create log entry with decision info
|
pdd/trace_main.py
CHANGED
|
@@ -39,7 +39,8 @@ def trace_main(ctx: click.Context, prompt_file: str, code_file: str, code_line:
|
|
|
39
39
|
force=ctx.obj.get('force', False),
|
|
40
40
|
quiet=quiet,
|
|
41
41
|
command="trace",
|
|
42
|
-
command_options=command_options
|
|
42
|
+
command_options=command_options,
|
|
43
|
+
context_override=ctx.obj.get('context')
|
|
43
44
|
)
|
|
44
45
|
logger.debug("File paths constructed successfully")
|
|
45
46
|
|
pdd/update_main.py
CHANGED
|
@@ -48,6 +48,7 @@ def update_main(
|
|
|
48
48
|
quiet=ctx.obj.get("quiet", False),
|
|
49
49
|
command="update",
|
|
50
50
|
command_options=command_options,
|
|
51
|
+
context_override=ctx.obj.get('context')
|
|
51
52
|
)
|
|
52
53
|
|
|
53
54
|
# Extract input strings
|
|
@@ -101,4 +102,4 @@ def update_main(
|
|
|
101
102
|
except Exception as e:
|
|
102
103
|
if not ctx.obj.get("quiet", False):
|
|
103
104
|
rprint(f"[bold red]Error:[/bold red] {str(e)}")
|
|
104
|
-
sys.exit(1)
|
|
105
|
+
sys.exit(1)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pdd-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.56
|
|
4
4
|
Summary: PDD (Prompt-Driven Development) Command Line Interface
|
|
5
5
|
Author: Greg Tanaka
|
|
6
6
|
Author-email: glt@alumni.caltech.edu
|
|
@@ -51,7 +51,7 @@ Requires-Dist: build; extra == "dev"
|
|
|
51
51
|
Requires-Dist: twine; extra == "dev"
|
|
52
52
|
Dynamic: license-file
|
|
53
53
|
|
|
54
|
-
.. image:: https://img.shields.io/badge/pdd--cli-v0.0.
|
|
54
|
+
.. image:: https://img.shields.io/badge/pdd--cli-v0.0.56-blue
|
|
55
55
|
:alt: PDD-CLI Version
|
|
56
56
|
|
|
57
57
|
.. image:: https://img.shields.io/badge/Discord-join%20chat-7289DA.svg?logo=discord&logoColor=white&link=https://discord.gg/Yp4RTh8bG7
|
|
@@ -128,7 +128,7 @@ After installation, verify:
|
|
|
128
128
|
|
|
129
129
|
pdd --version
|
|
130
130
|
|
|
131
|
-
You'll see the current PDD version (e.g., 0.0.
|
|
131
|
+
You'll see the current PDD version (e.g., 0.0.56).
|
|
132
132
|
|
|
133
133
|
Getting Started with Examples
|
|
134
134
|
-----------------------------
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
pdd/__init__.py,sha256=
|
|
2
|
-
pdd/auto_deps_main.py,sha256=
|
|
1
|
+
pdd/__init__.py,sha256=ca8MfVovv1zfjBoDhLPWEWu1bOMwbT7XY3CcRF635Sg,633
|
|
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
|
|
5
|
-
pdd/bug_main.py,sha256=
|
|
5
|
+
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
|
-
pdd/change_main.py,sha256=
|
|
9
|
-
pdd/cli.py,sha256=
|
|
10
|
-
pdd/cmd_test_main.py,sha256=
|
|
8
|
+
pdd/change_main.py,sha256=04VHiO_D-jlfeRn6rrVH7ZTA5agXPoJGm1StGI8--XY,27804
|
|
9
|
+
pdd/cli.py,sha256=njGVezstZGTeinhrUdOQ2K21Wpt1jiA5jU6BT7OZpaY,46782
|
|
10
|
+
pdd/cmd_test_main.py,sha256=M-i5x26ORXurt_pu8x1sgLAyVIItbuRThiux4wBg3Ls,7768
|
|
11
11
|
pdd/code_generator.py,sha256=AxMRZKGIlLh9xWdn2FA6b3zSoZ-5TIZNIAzqjFboAQs,4718
|
|
12
|
-
pdd/code_generator_main.py,sha256=
|
|
12
|
+
pdd/code_generator_main.py,sha256=RwyjzrC1NHOfJJkfxdwWwJf_UNAy2lCWjSyasucG2KU,27997
|
|
13
13
|
pdd/comment_line.py,sha256=sX2hf4bG1fILi_rvI9MkkwCZ2IitgKkW7nOiw8aQKPY,1845
|
|
14
14
|
pdd/conflicts_in_prompts.py,sha256=9N3rZWdJUGayOTOgnHW9G_Jm1C9G4Y8hSLhnURc1BkY,4890
|
|
15
|
-
pdd/conflicts_main.py,sha256=
|
|
16
|
-
pdd/construct_paths.py,sha256=
|
|
15
|
+
pdd/conflicts_main.py,sha256=SK8eljbAY_wWT4dieRSsQwBrU1Dm90MImry3AGL-Dj4,3704
|
|
16
|
+
pdd/construct_paths.py,sha256=BDXDazbMOwgSLbYhCmgUwYIg0QPrjj8AVRbmFGJQIm4,33966
|
|
17
17
|
pdd/context_generator.py,sha256=HAptXNSFTGu4rHw2SceiCcoCunIemESNCMVNqY1w6hU,6107
|
|
18
|
-
pdd/context_generator_main.py,sha256=
|
|
18
|
+
pdd/context_generator_main.py,sha256=ORpokRM9ZToBdMhFpM76iXkCGySyv2wsbQiyl4Ir5lQ,4147
|
|
19
19
|
pdd/continue_generation.py,sha256=nEkAKZd9lM7OelQkffP99Y-JLxTFZeY3AH9VLRQCjHg,7854
|
|
20
|
-
pdd/crash_main.py,sha256=
|
|
20
|
+
pdd/crash_main.py,sha256=ICiMbpCxdu6bjtLssKgTlVQK3PXXXjFRAX9CL0VJuH8,7665
|
|
21
21
|
pdd/detect_change.py,sha256=mA6k62xqeU1UG__CjzveJK0JDiRAO7AAC-JUfS0i2HQ,5510
|
|
22
|
-
pdd/detect_change_main.py,sha256=
|
|
22
|
+
pdd/detect_change_main.py,sha256=aEehiFlKAfqegW6e18gVMKxbcSQpV9gqLpyX7Bl7Chw,3863
|
|
23
23
|
pdd/edit_file.py,sha256=-FhZ-KGKYkPbnt0zFiDnnosPLh3bbKmften0Ios4-90,35017
|
|
24
24
|
pdd/find_section.py,sha256=lz_FPY4KDCRAGlL1pWVZiutUNv7E4KsDFK-ymDWA_Ec,962
|
|
25
25
|
pdd/fix_code_loop.py,sha256=LQXYQuFMjMM4yo6oJaFKyCg9OHpFwATp6QeHm8TsGR4,24468
|
|
26
26
|
pdd/fix_code_module_errors.py,sha256=jKH88KunVhof1MYRI_F42_YnLt5k4lif4YztQgzB9g8,5446
|
|
27
27
|
pdd/fix_error_loop.py,sha256=lhJrfJuFi_dB7hWTbpJfLEEZaltaRXYDl0XScDLvbdk,26464
|
|
28
28
|
pdd/fix_errors_from_unit_tests.py,sha256=fIqEfVIEx8PPSAzWu5nhin_remKu4c0_o51AN3g_x6s,9398
|
|
29
|
-
pdd/fix_main.py,sha256=
|
|
29
|
+
pdd/fix_main.py,sha256=F0A9nv0ayYAqTMthluAzw2gvuFwEcZpec_0v8Krfd0s,14058
|
|
30
30
|
pdd/fix_verification_errors.py,sha256=HvqGGdQqHq7OERmzcYP8Ft5nX_xthwVPJPG-YLv6VNM,17444
|
|
31
31
|
pdd/fix_verification_errors_loop.py,sha256=80899aKg27wM9-I5wOoiHbbla5Bfm0bOibx7WNmiWPE,55715
|
|
32
|
-
pdd/fix_verification_main.py,sha256=
|
|
32
|
+
pdd/fix_verification_main.py,sha256=lnhe4Sr6eV8EZEOTsSrzgxB_Ili5OJ0ZeFij_4Coc-E,24289
|
|
33
33
|
pdd/generate_output_paths.py,sha256=YYxeEKiHf39s-giDu4ak_xufyfRqkuCcvowVuOytXaI,24224
|
|
34
34
|
pdd/generate_test.py,sha256=Kd-iZnbHhGsgY6aD7Nu3i10ZNDpu3CVQROwAOYcjBok,6993
|
|
35
35
|
pdd/get_comment.py,sha256=yuRtk68-SDkMaGzOSyIFdldRoymJBRSKjOYkr0narVc,2627
|
|
@@ -51,26 +51,26 @@ pdd/pdd_completion.zsh,sha256=f4BxXrLZUEcFeIUmXWdnFOTnTpJBFZ8KGpnIdjDdKFo,15353
|
|
|
51
51
|
pdd/postprocess.py,sha256=mNw3iSDxE-eTYo3QwJCj_EmdEnnB5ysUN62YPapC_IM,4433
|
|
52
52
|
pdd/postprocess_0.py,sha256=OW17GyCFLYErCyWh2tL4syuho3q2yFf2wyekQ4BLdPM,2168
|
|
53
53
|
pdd/preprocess.py,sha256=XdMSJDqkMQk_wO7ysOYELIpIXEIig-9pBqiEhm9QdsU,10108
|
|
54
|
-
pdd/preprocess_main.py,sha256=
|
|
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
|
|
57
57
|
pdd/python_env_detector.py,sha256=y-QESoPNiKaD821uz8okX-9qA-oqvH9cQHY2_MwFHzU,5194
|
|
58
58
|
pdd/split.py,sha256=9lWrh-JOjOpxRp4-s1VL7bqJMVWlsmY5LxONT7sYM8A,5288
|
|
59
|
-
pdd/split_main.py,sha256=
|
|
59
|
+
pdd/split_main.py,sha256=52rcZoeS_wpYRiqbqMUgr_hUY7GS62otwzDfuAGi6YA,4845
|
|
60
60
|
pdd/summarize_directory.py,sha256=BR3-yGcmUdDT26vWLGokBo6mAZzaT7PzoY_qZriH3cc,10061
|
|
61
61
|
pdd/sync_animation.py,sha256=e7Qb4m70BHYpl37CuuF-95j-APctPL4Zm_o1PSTTRFQ,28070
|
|
62
|
-
pdd/sync_determine_operation.py,sha256=
|
|
63
|
-
pdd/sync_main.py,sha256=
|
|
64
|
-
pdd/sync_orchestration.py,sha256=
|
|
62
|
+
pdd/sync_determine_operation.py,sha256=o4wQSaOP3rGzkPuB5aVySdzhYdHiMWQvXFZPHZl99pc,60248
|
|
63
|
+
pdd/sync_main.py,sha256=MrQldtBDeClNPtBECRR4Sy5LM_-TkPSNSnuNXdTxb10,13744
|
|
64
|
+
pdd/sync_orchestration.py,sha256=tQydUxozSikHbXWBb8GtZMEDR3aRwePKdEGZukuH6uM,69966
|
|
65
65
|
pdd/trace.py,sha256=Ty-r3ZQC5k3PUCUacgfzg4sO8RgcH8kquSDau-jHkec,10874
|
|
66
|
-
pdd/trace_main.py,sha256=
|
|
66
|
+
pdd/trace_main.py,sha256=SOnMEHta9WaMAxulMrk6aFojma4ti61ILvJp3NVhpbg,4992
|
|
67
67
|
pdd/track_cost.py,sha256=vsLrQmipjG1BW4P9Wl33qoS8XFJDYBVY4ruQqKjPEx0,4238
|
|
68
68
|
pdd/unfinished_prompt.py,sha256=8En5NZqg6eCL6b451T_ndJx5ln1XDtFJyieW4pKRakE,5955
|
|
69
|
-
pdd/update_main.py,sha256=
|
|
69
|
+
pdd/update_main.py,sha256=SWCd7Us3YatrDR7B66dQCpRCIgQoMHysPzxa4dedVmk,4385
|
|
70
70
|
pdd/update_model_costs.py,sha256=RfeOlAHtc1FCx47A7CjrH2t5WXQclQ_9uYtNjtQh75I,22998
|
|
71
71
|
pdd/update_prompt.py,sha256=zc-HiI1cwGBkJHVmNDyoSZa13lZH90VdB9l8ajdj6Kk,4543
|
|
72
72
|
pdd/xml_tagger.py,sha256=5Bc3HRm7iz_XjBdzQIcMb8KocUQ8PELI2NN5Gw4amd4,4825
|
|
73
|
-
pdd/data/language_format.csv,sha256=
|
|
73
|
+
pdd/data/language_format.csv,sha256=pWF3yCh6xOFNmrr2TxTnye7EPKT3c-LPjmYV3Qc0a-Y,933
|
|
74
74
|
pdd/data/llm_model.csv,sha256=UxllgS0btSpCKpPgPnaTFAtZsAynBhLeZyoIVo0Tpwc,1698
|
|
75
75
|
pdd/prompts/auto_include_LLM.prompt,sha256=sNF2rdJu9wJ8c0lwjCfZ9ZReX8zGXRUNehRs1ZiyDoc,12108
|
|
76
76
|
pdd/prompts/bug_to_unit_test_LLM.prompt,sha256=KdMkvRVnjVSf0NTYIaDXIMT93xPttXEwkMpjWx5leLs,1588
|
|
@@ -108,9 +108,9 @@ pdd/prompts/trim_results_start_LLM.prompt,sha256=OKz8fAf1cYWKWgslFOHEkUpfaUDARh3
|
|
|
108
108
|
pdd/prompts/unfinished_prompt_LLM.prompt,sha256=vud_G9PlVv9Ig64uBC-hPEVFRk5lwpc8pW6tOIxJM4I,5082
|
|
109
109
|
pdd/prompts/update_prompt_LLM.prompt,sha256=prIc8uLp2jqnLTHt6JvWDZGanPZipivhhYeXe0lVaYw,1328
|
|
110
110
|
pdd/prompts/xml_convertor_LLM.prompt,sha256=YGRGXJeg6EhM9690f-SKqQrKqSJjLFD51UrPOlO0Frg,2786
|
|
111
|
-
pdd_cli-0.0.
|
|
112
|
-
pdd_cli-0.0.
|
|
113
|
-
pdd_cli-0.0.
|
|
114
|
-
pdd_cli-0.0.
|
|
115
|
-
pdd_cli-0.0.
|
|
116
|
-
pdd_cli-0.0.
|
|
111
|
+
pdd_cli-0.0.56.dist-info/licenses/LICENSE,sha256=kvTJnnxPVTYlGKSY4ZN1kzdmJ0lxRdNWxgupaB27zsU,1066
|
|
112
|
+
pdd_cli-0.0.56.dist-info/METADATA,sha256=xVQb-QcyhglRDa-RDyTZ4EuSvQccTUcdlfaL5L8PR9s,12597
|
|
113
|
+
pdd_cli-0.0.56.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
114
|
+
pdd_cli-0.0.56.dist-info/entry_points.txt,sha256=Kr8HtNVb8uHZtQJNH4DnF8j7WNgWQbb7_Pw5hECSR-I,36
|
|
115
|
+
pdd_cli-0.0.56.dist-info/top_level.txt,sha256=xjnhIACeMcMeDfVNREgQZl4EbTni2T11QkL5r7E-sbE,4
|
|
116
|
+
pdd_cli-0.0.56.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|