Skip to content

Commit 2a6d660

Browse files
committed
Merge remote-tracking branch 'origin/main' into fix/java-generic-method-type-erasure
2 parents 9544e4b + 58c1bdf commit 2a6d660

198 files changed

Lines changed: 15464 additions & 25953 deletions

File tree

Some content is hidden

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

.claude/hooks/bash-guard.sh

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env bash
2+
# PreToolUse hook: Block Bash calls that should use dedicated tools.
3+
# Exit 0 = allow, Exit 2 = block (message on stderr).
4+
5+
INPUT=$(cat 2>/dev/null || true)
6+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null || true)
7+
8+
[ -z "$COMMAND" ] && exit 0
9+
10+
# Strip leading env vars (FOO=bar cmd ...) and whitespace to get the actual command
11+
STRIPPED=$(echo "$COMMAND" | sed 's/^[[:space:]]*\([A-Za-z_][A-Za-z0-9_]*=[^[:space:]]*[[:space:]]*\)*//')
12+
FIRST_CMD=$(echo "$STRIPPED" | awk '{print $1}')
13+
14+
case "$FIRST_CMD" in
15+
grep|egrep|fgrep|rg)
16+
echo "BLOCKED: Use the Grep tool instead of \`$FIRST_CMD\`. It provides better output and permissions handling." >&2
17+
exit 2
18+
;;
19+
find)
20+
echo "BLOCKED: Use the Glob tool instead of \`find\`. Glob is faster and returns results sorted by modification time." >&2
21+
exit 2
22+
;;
23+
cat|head|tail)
24+
echo "BLOCKED: Use the Read tool instead of \`$FIRST_CMD\`. Read provides line numbers and supports images/PDFs." >&2
25+
exit 2
26+
;;
27+
awk)
28+
echo "BLOCKED: Use the Grep tool or Read tool instead of \`awk\`." >&2
29+
exit 2
30+
;;
31+
sed)
32+
if echo "$COMMAND" | grep -qE '(^|[[:space:]])sed[[:space:]]+-i'; then
33+
echo "BLOCKED: Use the Edit tool instead of \`sed -i\`. Edit tracks changes properly." >&2
34+
exit 2
35+
fi
36+
;;
37+
esac
38+
39+
# echo with file redirection (echo "..." > file)
40+
if echo "$STRIPPED" | grep -qE '^echo\b.*[[:space:]]>'; then
41+
echo "BLOCKED: Use the Write tool instead of \`echo >\`. Write provides proper file creation." >&2
42+
exit 2
43+
fi
44+
45+
exit 0

.claude/hooks/post-compact.sh

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env bash
2+
# PreCompact hook: Inject state preservation guidance before context compaction.
3+
4+
cd "$CLAUDE_PROJECT_DIR" 2>/dev/null || exit 0
5+
6+
STATE=""
7+
8+
BRANCH=$(git branch --show-current 2>/dev/null)
9+
[ -n "$BRANCH" ] && STATE="${STATE}Branch: ${BRANCH}\n"
10+
11+
DIRTY=$(git status --porcelain 2>/dev/null)
12+
if [ -n "$DIRTY" ]; then
13+
COUNT=$(echo "$DIRTY" | wc -l | tr -d ' ')
14+
STATE="${STATE}Uncommitted files (${COUNT}):\n${DIRTY}\n"
15+
fi
16+
17+
UPSTREAM=$(git rev-parse --abbrev-ref '@{upstream}' 2>/dev/null)
18+
if [ -n "$UPSTREAM" ]; then
19+
AHEAD=$(git rev-list --count "${UPSTREAM}..HEAD" 2>/dev/null)
20+
[ "$AHEAD" -gt 0 ] 2>/dev/null && STATE="${STATE}Unpushed commits: ${AHEAD}\n"
21+
fi
22+
23+
RECENT=$(git log --oneline -5 2>/dev/null)
24+
[ -n "$RECENT" ] && STATE="${STATE}Recent commits:\n${RECENT}\n"
25+
26+
LATEST_HANDOFF=$(ls -t "$CLAUDE_PROJECT_DIR/.claude/handoffs/"*.md 2>/dev/null | head -1)
27+
if [ -n "$LATEST_HANDOFF" ] && [ -f "$LATEST_HANDOFF" ]; then
28+
HANDOFF_CONTENT=$(head -40 "$LATEST_HANDOFF" 2>/dev/null)
29+
[ -n "$HANDOFF_CONTENT" ] && STATE="${STATE}\nHandoff context:\n${HANDOFF_CONTENT}\n"
30+
fi
31+
32+
STATE="${STATE}\nProject conventions to preserve:\n"
33+
STATE="${STATE}- Python 3.9+, uv for all tooling, ruff + mypy via prek\n"
34+
STATE="${STATE}- Verification: uv run prek (single command for lint/format/types)\n"
35+
STATE="${STATE}- Pre-push: uv run prek run --from-ref origin/<base>\n"
36+
STATE="${STATE}- Conventional commits: fix:, feat:, refactor:, test:, chore:\n"
37+
STATE="${STATE}- Result type: Success(value) / Failure(error), check with is_successful()\n"
38+
STATE="${STATE}- Language singleton: set_current_language() / current_language()\n"
39+
STATE="${STATE}- libcst for code transforms, ast for read-only analysis\n"
40+
41+
[ -z "$STATE" ] && exit 0
42+
43+
EXPANDED=$(printf '%b' "$STATE")
44+
jq -n --arg msg "PRESERVE the following session state through compaction:
45+
$EXPANDED" '{"systemMessage": $msg}'
46+
47+
exit 0

.claude/hooks/post-edit-lint.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/usr/bin/env bash
2-
# Everyone is on macOS so this should be fine, we don't account for Windows
32
set -euo pipefail
43

54
input=$(cat)
@@ -10,6 +9,5 @@ if [[ -z "$file_path" || ! -f "$file_path" ]]; then
109
fi
1110

1211
if [[ "$file_path" == *.py ]]; then
13-
# First run auto-fixes formatting; second run catches real lint errors
1412
uv run prek --files "$file_path" 2>/dev/null || uv run prek --files "$file_path"
1513
fi

.claude/hooks/require-read.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bash
2+
# PreToolUse hook: Block Write/Edit on existing files that haven't been Read first.
3+
# Exit 0 = allow, Exit 2 = block (message on stderr).
4+
5+
INPUT=$(cat 2>/dev/null || true)
6+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null || true)
7+
8+
[ -z "$FILE_PATH" ] && exit 0
9+
10+
# New files don't need prior reads
11+
[ ! -f "$FILE_PATH" ] && exit 0
12+
13+
TRACKER="$CLAUDE_PROJECT_DIR/.claude/.read-tracker"
14+
15+
if [ ! -f "$TRACKER" ]; then
16+
echo "BLOCKED: Read \`$(basename "$FILE_PATH")\` first before modifying it." >&2
17+
exit 2
18+
fi
19+
20+
if grep -qxF "$FILE_PATH" "$TRACKER"; then
21+
exit 0
22+
fi
23+
24+
echo "BLOCKED: Read \`$(basename "$FILE_PATH")\` first before modifying it." >&2
25+
exit 2

.claude/hooks/status-line.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/env bash
2+
# Status line: derive context from git state.
3+
4+
input=$(cat)
5+
project_dir=$(echo "$input" | jq -r '.workspace.project_dir')
6+
7+
user=$(whoami)
8+
branch=$(git -C "$project_dir" branch --show-current 2>/dev/null)
9+
10+
changed=$(git -C "$project_dir" diff --name-only HEAD 2>/dev/null)
11+
[ -z "$changed" ] && changed=$(git -C "$project_dir" diff --name-only 2>/dev/null)
12+
[ -z "$changed" ] && changed=$(git -C "$project_dir" diff --name-only --cached 2>/dev/null)
13+
14+
if [ -n "$changed" ]; then
15+
area=$(echo "$changed" | sed 's|/.*||' | sort | uniq -c | sort -rn | head -1 | awk '{print $2}')
16+
else
17+
area=""
18+
fi
19+
20+
context=""
21+
case "$area" in
22+
codeflash)
23+
subsystem=$(echo "$changed" | grep '^codeflash/' | sed 's|^codeflash/||; s|/.*||' | sort | uniq -c | sort -rn | head -1 | awk '{print $2}')
24+
[ -n "$subsystem" ] && context="editing $subsystem" ;;
25+
tests)
26+
target=$(echo "$changed" | grep '^tests/' | sed 's|^tests/||; s|/.*||' | sort -u | head -1)
27+
[ -n "$target" ] && context="testing $target" ;;
28+
.claude)
29+
context="configuring claude" ;;
30+
esac
31+
32+
if [ -z "$context" ] && [ -n "$branch" ]; then
33+
case "$branch" in
34+
feat/*|cf-*) context="building: ${branch#feat/}" ;;
35+
fix/*) context="fixing: ${branch#fix/}" ;;
36+
refactor/*) context="refactoring: ${branch#refactor/}" ;;
37+
test/*) context="testing: ${branch#test/}" ;;
38+
chore/*) context="chore: ${branch#chore/}" ;;
39+
esac
40+
fi
41+
42+
dirty=""
43+
if [ -n "$(git -C "$project_dir" status --porcelain 2>/dev/null)" ]; then
44+
dirty=" *"
45+
fi
46+
47+
status="$user | codeflash"
48+
[ -n "$context" ] && status="$status | $context"
49+
[ -n "$branch" ] && status="$status | $branch$dirty"
50+
echo "$status"

.claude/hooks/track-read.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env bash
2+
# PostToolUse hook: Track Read calls for the require-read guard.
3+
4+
INPUT=$(cat 2>/dev/null || true)
5+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null || true)
6+
7+
[ -z "$FILE_PATH" ] && exit 0
8+
9+
TRACKER="$CLAUDE_PROJECT_DIR/.claude/.read-tracker"
10+
grep -qxF "$FILE_PATH" "$TRACKER" 2>/dev/null || echo "$FILE_PATH" >> "$TRACKER"
11+
exit 0

.claude/rules/architecture.md

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ codeflash/
2121
├── api/ # AI service communication
2222
├── code_utils/ # Code parsing, git utilities
2323
├── models/ # Pydantic models and types
24-
├── languages/ # Multi-language support (Python, JavaScript/TypeScript, Java planned)
24+
├── languages/ # Multi-language support (Python, JavaScript/TypeScript, Java)
2525
│ ├── base.py # LanguageSupport protocol and shared data types
2626
│ ├── registry.py # Language registration and lookup by extension/enum
2727
│ ├── current.py # Current language singleton (set_current_language / current_language_support)
@@ -35,11 +35,29 @@ codeflash/
3535
│ │ ├── test_runner.py # Test subprocess execution for Python
3636
│ │ ├── instrument_codeflash_capture.py # Instrument __init__ with capture decorators
3737
│ │ └── parse_line_profile_test_output.py # Parse line profiler output
38-
│ └── javascript/
39-
│ ├── support.py # JavaScriptSupport (LanguageSupport implementation)
40-
│ ├── function_optimizer.py # JavaScriptFunctionOptimizer subclass
41-
│ ├── optimizer.py # JS project root finding & module preparation
42-
│ └── normalizer.py # JS/TS code normalization for deduplication
38+
│ ├── javascript/
39+
│ │ ├── support.py # JavaScriptSupport (LanguageSupport implementation)
40+
│ │ ├── function_optimizer.py # JavaScriptFunctionOptimizer subclass
41+
│ │ ├── optimizer.py # JS project root finding & module preparation
42+
│ │ └── normalizer.py # JS/TS code normalization for deduplication
43+
│ └── java/
44+
│ ├── support.py # JavaSupport (LanguageSupport implementation)
45+
│ ├── function_optimizer.py # JavaFunctionOptimizer subclass
46+
│ ├── build_tool_strategy.py # Abstract BuildToolStrategy for Maven/Gradle
47+
│ ├── maven_strategy.py # Maven build tool strategy
48+
│ ├── gradle_strategy.py # Gradle build tool strategy
49+
│ ├── build_tools.py # Build tool detection and project info
50+
│ ├── build_config_strategy.py # Config read/write for pom.xml / gradle.properties
51+
│ ├── test_runner.py # Test execution via Maven/Gradle
52+
│ ├── instrumentation.py # Behavior capture and benchmarking instrumentation
53+
│ ├── discovery.py # Function discovery using tree-sitter
54+
│ ├── test_discovery.py # Test discovery for JUnit/TestNG
55+
│ ├── context.py # Code context extraction
56+
│ ├── comparator.py # Test result comparison
57+
│ ├── config.py # Java project detection and config
58+
│ ├── formatter.py # Code formatting and normalization
59+
│ ├── line_profiler.py # JVM bytecode agent-based line profiling
60+
│ └── tracer.py # Two-stage JFR + argument capture tracer
4361
├── setup/ # Config schema, auto-detection, first-run experience
4462
├── picklepatch/ # Serialization/deserialization utilities
4563
├── tracing/ # Function call tracing
@@ -57,7 +75,7 @@ codeflash/
5775
|------|------------|
5876
| CLI arguments & commands | `cli_cmds/cli.py` (parsing), `main.py` (subcommand dispatch) |
5977
| Optimization orchestration | `optimization/optimizer.py``run()` |
60-
| Per-function optimization | `languages/function_optimizer.py` (base), `languages/python/function_optimizer.py`, `languages/javascript/function_optimizer.py` |
78+
| Per-function optimization | `languages/function_optimizer.py` (base), `languages/python/function_optimizer.py`, `languages/javascript/function_optimizer.py`, `languages/java/function_optimizer.py` |
6179
| Function discovery | `discovery/functions_to_optimize.py` |
6280
| Context extraction | `languages/<lang>/context/code_context_extractor.py` |
6381
| Test execution | `languages/<lang>/support.py` (`run_behavioral_tests`, etc.), `verification/pytest_plugin.py` |
@@ -67,7 +85,7 @@ codeflash/
6785

6886
## LanguageSupport Protocol Methods
6987

70-
Core protocol in `languages/base.py`. Each language (`PythonSupport`, `JavaScriptSupport`) implements these.
88+
Core protocol in `languages/base.py`. Each language (`PythonSupport`, `JavaScriptSupport`, `JavaSupport`) implements these.
7189

7290
| Category | Method/Property | Purpose |
7391
|----------|----------------|---------|

.claude/rules/code-style.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
- **Python**: 3.9+ syntax
55
- **Package management**: Always use `uv`, never `pip`
66
- **Tooling**: Ruff for linting/formatting, mypy strict mode, prek for pre-commit checks
7-
- **Comments**: Minimal - only explain "why", not "what"
8-
- **Docstrings**: Do not add docstrings to new or changed code unless the user explicitly asks for them — not even one-liners. The codebase intentionally keeps functions self-documenting through clear naming and type annotations
9-
- **Types**: Match the type annotation style of surrounding code — the codebase uses annotations, so add them in new code
10-
- **Naming**: NEVER use leading underscores (`_function_name`) - Python has no true private functions, use public names
7+
- **Comments**: Minimal only explain "why", not "what"
8+
- **Docstrings**: Do not add docstrings unless the user explicitly asks
9+
- **Types**: Match the type annotation style of surrounding code
10+
- **Naming**: No leading underscores (`_function_name`) Python has no true private functions
1111
- **Paths**: Always use absolute paths
12-
- **Encoding**: Always pass `encoding="utf-8"` to `open()`, `read_text()`, `write_text()`, etc. in new or changed code — Windows defaults to `cp1252` which breaks on non-ASCII content. Don't flag pre-existing code that lacks it unless you're already modifying that line.
13-
- **Verification**: Use `uv run prek` to verify code — it handles ruff, ty, mypy in one pass. Don't run `ruff`, `mypy`, or `python -c "import ..."` separately; `prek` is the single verification command
12+
- **Encoding**: Always pass `encoding="utf-8"` to `open()`, `read_text()`, `write_text()` in new or changed code
13+
- **Verification**: Use `uv run prek` — it handles ruff, ty, mypy in one pass. Don't run them separately
14+
- **Code transforms**: Use `libcst` for code modification/transformation. `ast` is acceptable for read-only analysis

.claude/rules/debugging.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Debugging
2+
3+
## Root cause first
4+
5+
When encountering a bug, investigate the root cause. Don't patch symptoms. If you're about to add a try/except, a fallback default, or a defensive check — ask whether the real fix is upstream.
6+
7+
## Isolated testing
8+
9+
Prefer running individual test functions over full suites. Only run the full suite when explicitly asked or before pushing.
10+
11+
- Single function: `uv run pytest tests/test_foo.py::TestBar::test_baz -v`
12+
- Single module: `uv run pytest tests/test_foo.py -v`
13+
- Full suite: only when asked, or before `git push`
14+
15+
When debugging a specific endpoint or integration, test it directly instead of running the entire pipeline end-to-end.
16+
17+
## Subprocess failures
18+
19+
When a subprocess fails, always log stdout and stderr. "Exit code 1" with no output is useless.

.claude/rules/git.md

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,35 @@
1-
# Git Commits & Pull Requests
1+
# Git
22

33
## Commits
4+
45
- Never commit, amend, or push without explicit permission
5-
- Don't commit intermediate states — wait until the full implementation is complete, reviewed, and explicitly approved before committing. If the user corrects direction mid-implementation, incorporate the correction before any commit
6-
- Always create a new branch from `main` before starting any new work — never commit directly to `main` or reuse an existing feature branch for unrelated changes
7-
- Use conventional commit format: `fix:`, `feat:`, `refactor:`, `docs:`, `test:`, `chore:`
8-
- Keep commits atomic - one logical change per commit
9-
- Commit message body should be concise (1-2 sentences max)
10-
- Merge for simple syncs, rebase when branches have diverged significantly
11-
- When committing to an external/third-party repo, follow that repo's own conventions for versioning, changelog, and CI
12-
- Pre-commit: Run `uv run prek` before committing — fix any issues before creating the commit
13-
- Pre-push: Run `uv run prek run --from-ref origin/<base>` to check all changed files against the PR base — this matches CI behavior and catches issues that per-commit prek misses. To detect the base branch: `gh pr view --json baseRefName -q .baseRefName 2>/dev/null || echo main`
6+
- Don't commit intermediate states — wait until the full implementation is complete and approved
7+
- Always create a new branch from `main` — never commit directly to `main`
8+
- Conventional format: `fix:`, `feat:`, `refactor:`, `docs:`, `test:`, `chore:`
9+
- First line: imperative verb + what changed, under 72 characters
10+
- Body for *why*, not *what* — the diff shows what changed
11+
- One purpose per commit: a bug fix, a new function, a refactor — not all three
12+
- A commit that adds a function also adds its tests and exports — that's one logical change
13+
14+
## Sizing
15+
16+
- Too small: renaming a variable in one commit, updating its references in another
17+
- Right size: adding a function with its tests, `__init__` export, and usage update
18+
- Too large: implementing an entire subsystem in one commit
19+
20+
## Pre-commit / Pre-push
21+
22+
- Pre-commit: Run `uv run prek` before committing
23+
- Pre-push: Run `uv run prek run --from-ref origin/<base>` to check all changed files against the PR base
1424

1525
## Pull Requests
16-
- PR titles should use conventional format
17-
- Keep the PR body short and straight to the point
26+
27+
- PR titles use conventional format
28+
- Keep the PR body short and to the point
1829
- If related to a Linear issue, include `CF-#` in the body
19-
- Branch naming: `cf-#-title` (lowercase, hyphenated), no other prefixes/suffixes
30+
- Branch naming: `cf-#-title` (lowercase, hyphenated)
31+
32+
## Branch Hygiene
33+
34+
- Delete feature branches locally after merging (`git branch -d <branch>`)
35+
- Use `/clean_gone` to prune local branches whose remote tracking branch has been deleted

0 commit comments

Comments
 (0)