Skip to content

Commit 2cde085

Browse files
committed
Bump version
1 parent 3c3a29d commit 2cde085

File tree

69 files changed

+7364
-663
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+7364
-663
lines changed

.env.example

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1-
OPENAI_API_KEY =your-openai-api-key
2-
GOOGLE_API_KEY = your-google-api-key
3-
ANTHROPIC_API_KEY = your-anthropic-api-key
4-
PDD_PATH = Where-Your-PDD-Root-Is-At
5-
DEEKSEEK_API_KEY = your-deekseek-api-key
6-
FIREWORKS_API_KEY = your-fireworks-api-key
7-
PYTHONPATH = staging/pdd
8-
GROQ_API_KEY = your-groq-api-key
9-
TOGETHER_API_KEY = your-together-api-key
1+
# LLM API Keys (at least one required)
2+
OPENAI_API_KEY=your-openai-api-key
3+
GOOGLE_API_KEY=your-google-api-key
4+
ANTHROPIC_API_KEY=your-anthropic-api-key
5+
6+
# Additional LLM Providers (optional)
7+
DEEPSEEK_API_KEY=your-deepseek-api-key
8+
FIREWORKS_API_KEY=your-fireworks-api-key
9+
GROQ_API_KEY=your-groq-api-key
10+
TOGETHER_API_KEY=your-together-api-key
11+
12+
# Vertex AI (optional - for Gemini via GCP)
13+
VERTEX_CREDENTIALS=/path/to/service-account.json
14+
VERTEX_PROJECT=your-gcp-project-id
15+
VERTEX_LOCATION=us-central1
16+
17+
# PDD Configuration
18+
PDD_PATH=/path/to/your/pdd

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ __pycache__/
33
*.py[cod]
44
*$py.class
55
*.vsix
6+
.tmp/
7+
.agentic_prompt*
68

79
.vscode/settings.json
810

.pddrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ contexts:
108108
test_output_path: "tests/"
109109
example_output_path: "context/"
110110
default_language: "python"
111-
target_coverage: 10.0
112-
strength: 0.8
111+
target_coverage: 80.0
112+
strength: 1
113113
temperature: 0.0
114114
budget: 10.0
115115
max_attempts: 3

CHANGELOG.md

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,65 @@
1+
## v0.0.89 (2025-12-22)
2+
3+
### Feat
4+
5+
- enhance working directory handling in agentic functions
6+
- enhance fix_error_loop documentation with control flow diagram
7+
- add --simple flag for legacy update mode in CLI
8+
- add simple option for legacy routing in update_main
9+
- refine fix_error_loop module with enhanced logging and iterative error handling
10+
- enhance git_update function with agentic and legacy routing logic
11+
- enhance auto_include and insert_includes to filter self-referential dependencies
12+
- enhance test coverage for agentic functionality with formal verification and unit tests
13+
- prioritize prompt changes in sync decision logic
14+
- enhance testing framework for agentic updates with formal verification and unit tests
15+
- implement crash_main and fix_code_loop functions for error handling
16+
- add formal verification and unit tests for agentic verification
17+
- add agentic verification functionality and example
18+
- implement agentic crash handling and testing framework
19+
- introduce agentic update functionality for prompt files
20+
21+
### Fix
22+
23+
- clarify prompt authority in error handling and test expectations
24+
- add progress callback parameter to test functions
25+
- ensure test file preservation during sync operations
26+
27+
### Refactor
28+
29+
- enhance agentic fix functionality and improve output reporting
30+
- enhance agentic functionality and improve CLI integration
31+
- enhance agentic functionality and prompt management
32+
- enhance clarity and structure in modify_python prompt
33+
- improve prompt clarity and structure in git_update and update_main
34+
- streamline agentic_fix and update prompts
35+
136
## v0.0.88 (2025-12-19)
237

338
### Feat
439

5-
- enhance configuration management and testing
40+
- **Multi-Test File Support for Fix Command:** The `pdd fix` command now accepts multiple unit test files as arguments. Each test file is processed separately by the LLM, enabling targeted fixes per test file rather than concatenating all tests into a single blob. Results are aggregated with overall success requiring all individual fixes to succeed.
41+
42+
- **Numbered Test Output Files:** The `test` and `bug` commands now automatically create numbered output files (e.g., `test_module_1.py`, `test_module_2.py`) when the output file already exists and `--force` is not specified, preventing accidental overwrites while maintaining workflow continuity.
43+
44+
- **Multi-File Existing Tests for Test Command:** The `--existing-tests` option in `cmd_test_main` now accepts multiple test file paths. All test file contents are concatenated and provided to the LLM for context-aware test generation.
45+
46+
Many thanks to Jiamin Cai for your contributions!
647

748
### Fix
849

9-
- adjust commit order in Makefile for public repo updates
50+
- **Setup Tool Shell Escaping:** Fixed a security and correctness issue where API keys containing special shell characters (`$`, `"`, `'`, `\`) would generate malformed shell scripts. Now uses `shlex.quote()` for proper POSIX shell escaping across bash, zsh, fish, and csh variants. Thank you to Dhruv Garg for your contributions!
51+
52+
- **Makefile Commit Order:** Adjusted commit order for public repository updates to ensure proper synchronization.
53+
54+
### Tests
55+
56+
- Added 574 lines of comprehensive tests for `setup_tool.py` in `tests/test_setup_tool.py` covering shell script generation with special characters for bash, zsh, fish, and csh.
57+
58+
- Added regression test #21 for multi-test file fix workflow, verifying end-to-end LLM-based fixes across multiple test files.
59+
60+
- Added tests for numbered test file output in `tests/test_construct_paths.py` verifying automatic file numbering behavior.
61+
62+
- Added tests for multi-file existing tests handling in `tests/test_cmd_test_main.py`.
1063

1164
## v0.0.87 (2025-12-18)
1265

Makefile

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,8 @@ release: check-deps
571571
else \
572572
echo "Bumping version with commitizen"; \
573573
python -m commitizen bump --increment PATCH --yes; \
574+
echo "Pushing to origin before publishing"; \
575+
git push origin main --tags; \
574576
echo "Publishing new version"; \
575577
$(MAKE) publish; \
576578
fi
@@ -713,7 +715,10 @@ publish-public:
713715
fi
714716
@echo "Committing and pushing updates in public repo"
715717
@if git -C "$(PUBLIC_PDD_REPO_DIR)" rev-parse --is-inside-work-tree >/dev/null 2>&1; then \
716-
cd "$(PUBLIC_PDD_REPO_DIR)" && git add . && git commit -m "Bump version" && git fetch origin && git rebase origin/main && git push; \
718+
cd "$(PUBLIC_PDD_REPO_DIR)" && git add . && git commit -m "Bump version" && git fetch origin && git rebase origin/main && \
719+
CURR_VER=$$(sed -n 's/^version[[:space:]]*=[[:space:]]*"\([0-9.]*\)"/\1/p' pyproject.toml | head -n1) && \
720+
(git tag -a "v$$CURR_VER" -m "Release v$$CURR_VER" 2>/dev/null || true) && \
721+
git push && git push --tags; \
717722
else \
718723
echo "Skip commit: $(PUBLIC_PDD_REPO_DIR) is not a Git repo. Set PUBLIC_PDD_REPO_DIR to a clone of $(PUBLIC_PDD_REMOTE)."; \
719724
fi
@@ -845,7 +850,10 @@ publish-public-cap:
845850
fi
846851
@echo "Committing and pushing updates in CAP public repo"
847852
@if git -C "$(PUBLIC_PDD_CAP_REPO_DIR)" rev-parse --is-inside-work-tree >/dev/null 2>&1; then \
848-
cd "$(PUBLIC_PDD_CAP_REPO_DIR)" && git add . && git commit -m "Bump version" && git fetch origin && git rebase origin/main && git push; \
853+
cd "$(PUBLIC_PDD_CAP_REPO_DIR)" && git add . && git commit -m "Bump version" && git fetch origin && git rebase origin/main && \
854+
CURR_VER=$$(sed -n 's/^version[[:space:]]*=[[:space:]]*"\([0-9.]*\)"/\1/p' pyproject.toml | head -n1) && \
855+
(git tag -a "v$$CURR_VER" -m "Release v$$CURR_VER" 2>/dev/null || true) && \
856+
git push && git push --tags; \
849857
else \
850858
echo "Skip commit: $(PUBLIC_PDD_CAP_REPO_DIR) is not a Git repo. Set PUBLIC_PDD_CAP_REPO_DIR to a clone of $(PUBLIC_PDD_CAP_REMOTE)."; \
851859
fi

README.md

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# PDD (Prompt-Driven Development) Command Line Interface
22

3-
![PDD-CLI Version](https://img.shields.io/badge/pdd--cli-v0.0.88-blue) [![Discord](https://img.shields.io/badge/Discord-join%20chat-7289DA.svg?logo=discord&logoColor=white)](https://discord.gg/Yp4RTh8bG7)
3+
![PDD-CLI Version](https://img.shields.io/badge/pdd--cli-v0.0.89-blue) [![Discord](https://img.shields.io/badge/Discord-join%20chat-7289DA.svg?logo=discord&logoColor=white)](https://discord.gg/Yp4RTh8bG7)
44

55
## Introduction
66

@@ -285,7 +285,7 @@ export PDD_TEST_OUTPUT_PATH=/path/to/tests/
285285

286286
## Version
287287

288-
Current version: 0.0.88
288+
Current version: 0.0.89
289289

290290
To check your installed version, run:
291291
```
@@ -1606,6 +1606,28 @@ pdd [GLOBAL OPTIONS] change --csv --output modified_prompts/ changes_batch.csv s
16061606
16071607
Update prompts based on code changes. This command operates in two primary modes:
16081608
1609+
**Agentic Prompt Optimization (Default)**
1610+
1611+
The `update` command uses an agentic AI (Claude Code, Gemini, or Codex) by default to produce compact, high-quality prompts. The agent has full file access and performs a 4-step optimization:
1612+
1613+
1. **Assess Differences**: Reads the prompt (including all `<include>` files) and compares against the modified code
1614+
2. **Filter Using Guide + Tests**: Consults `docs/prompting_guide.md` and existing tests to determine what belongs in the prompt
1615+
3. **Remove Duplication**: Eliminates redundant content that duplicates included files
1616+
4. **Validate**: Ensures the prompt is human-readable and can reliably regenerate the code
1617+
1618+
This produces prompts that are more concise while remaining clear to developers and reliable for code generation.
1619+
1620+
**Prerequisites**: Requires one of these CLI tools installed and configured:
1621+
- `claude` (Anthropic Claude Code)
1622+
- `gemini` (Google Gemini CLI)
1623+
- `codex` (OpenAI Codex CLI)
1624+
1625+
If no agentic CLI is available, the command automatically falls back to the legacy 2-stage LLM update process.
1626+
1627+
**Test-Aware Updates**: When tests exist for a module (e.g., `test_my_module.py`, `test_my_module_1.py`), the agentic update automatically discovers and considers them. Behaviors verified by tests don't need to be explicitly specified in the prompt, resulting in more compact prompts.
1628+
1629+
**Modes:**
1630+
16091631
1. **Repository-Wide Mode (Default)**: When run with no file arguments, `pdd update` scans the entire repository. It finds all code/prompt pairs, creates any missing prompt files, and updates all of them based on the latest Git changes. This is the easiest way to keep your entire project in sync.
16101632
16111633
2. **Single-File Mode**: When you provide file arguments, the command operates on a specific file. There are three distinct use cases for this mode:
@@ -1657,13 +1679,23 @@ Options:
16571679
- `--output LOCATION`: Specify where to save the updated prompt file. **If not specified, the original prompt file is overwritten to maintain it as the authoritative source of truth.** If an environment variable `PDD_UPDATE_OUTPUT_PATH` is set, it will be used only when `--output` is explicitly omitted and you want a different default location.
16581680
- `--git`: Use git history to find the original code file, eliminating the need for the `INPUT_CODE_FILE` argument.
16591681
- `--extensions EXTENSIONS`: In repository-wide mode, filter the update to only include files with the specified comma-separated extensions (e.g., `py,js,ts`).
1682+
- `--simple`: Use the legacy 2-stage LLM update process instead of the default agentic mode. Useful when agentic CLIs are not available or for faster updates.
16601683
16611684
Example (overwrite original prompt - default behavior):
16621685
```
16631686
pdd [GLOBAL OPTIONS] update factorial_calculator_python.prompt src/modified_factorial_calculator.py src/original_factorial_calculator.py
16641687
# This overwrites factorial_calculator_python.prompt in place
16651688
```
16661689
1690+
Example (agentic vs simple mode):
1691+
```bash
1692+
# Default: Agentic mode (uses claude/gemini/codex for intelligent optimization)
1693+
pdd update --git my_module_python.prompt src/my_module.py
1694+
1695+
# Legacy: Simple 2-stage LLM update (faster, no agentic CLI required)
1696+
pdd update --simple --git my_module_python.prompt src/my_module.py
1697+
```
1698+
16671699
16681700
16691701

context/agentic_common_example.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from __future__ import annotations
2+
3+
import os
4+
import sys
5+
from pathlib import Path
6+
7+
# Add the project root to sys.path to allow importing the pdd package
8+
# This assumes the script is located in pdd/context/ relative to the package root
9+
project_root = Path(__file__).resolve().parent.parent
10+
sys.path.append(str(project_root))
11+
12+
from pdd.agentic_common import get_available_agents, run_agentic_task
13+
14+
15+
def main() -> None:
16+
"""
17+
Demonstrates how to use the agentic_common module to:
18+
1. Discover available agent providers (Claude, Gemini, Codex).
19+
2. Run a headless agentic task to create a file.
20+
3. Parse the results including cost and provider used.
21+
"""
22+
23+
# 1. Setup the environment
24+
# We will use a local './output' directory as the agent's working directory (cwd).
25+
# The agent will have permission to read/write files in this directory.
26+
output_dir = Path("./output")
27+
output_dir.mkdir(exist_ok=True)
28+
29+
print(f"Agent working directory: {output_dir.resolve()}")
30+
31+
# 2. Check availability
32+
# get_available_agents() checks if the CLI tool is on PATH and if API keys are set.
33+
agents = get_available_agents()
34+
print(f"Available agents: {agents}")
35+
36+
if not agents:
37+
print("Warning: No agents detected. Ensure CLI tools (claude, gemini, codex) are installed and API keys are set.")
38+
print("The run_agentic_task call below will fail gracefully.")
39+
40+
# 3. Define the task
41+
# The instruction is natural language. We ask the agent to write a specific Python script.
42+
instruction = (
43+
"Create a file named 'generated_math.py'. "
44+
"Inside it, write a Python function 'calculate_factorial(n)' that returns the factorial of n. "
45+
"Add a main block that prints the factorial of 5."
46+
)
47+
48+
print(f"\n--- Running Task: {instruction} ---")
49+
50+
# 4. Run the agentic task
51+
# - cwd: The directory where the agent operates.
52+
# - verbose: Prints debug logs (useful to see CLI commands).
53+
# - label: A prefix for logs to identify this specific task.
54+
success, output_message, cost, provider_used = run_agentic_task(
55+
instruction=instruction,
56+
cwd=output_dir,
57+
verbose=True,
58+
quiet=False,
59+
label="demo"
60+
)
61+
62+
# 5. Inspect Results
63+
print("\n--- Execution Results ---")
64+
print(f"Success : {success}")
65+
print(f"Provider Used : {provider_used if provider_used else 'None'}")
66+
print(f"Estimated Cost: ${cost:.6f}")
67+
print(f"Agent Output : {output_message}")
68+
69+
# 6. Verify the side effects (File Creation)
70+
if success:
71+
target_file = output_dir / "generated_math.py"
72+
if target_file.exists():
73+
print(f"\n[Verification] File '{target_file.name}' was created successfully.")
74+
content = target_file.read_text(encoding="utf-8")
75+
print("File Content:")
76+
print("-" * 40)
77+
print(content)
78+
print("-" * 40)
79+
else:
80+
print(f"\n[Verification] Task succeeded, but file '{target_file.name}' was not found.")
81+
82+
83+
if __name__ == "__main__":
84+
main()

0 commit comments

Comments
 (0)