Skip to content

Commit 8e5c11a

Browse files
AndyMik90claude
andauthored
chore: bump version to 2.7.2-beta.12 (#460)
* chore: bump version to 2.7.2-beta.12 Update package.json version to match the latest beta release so the auto-updater correctly detects the current version. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(hooks): update both URL path and filename in README download links The version sync in pre-commit only updated Auto-Claude-X.Y.Z filename patterns but not the /download/vX.Y.Z/ URL path, resulting in broken download links (e.g., /download/v2.7.1/Auto-Claude-2.8.0-win32.exe). Now uses section-aware updates: - Prerelease versions only update BETA_* sections - Stable versions only update STABLE_* and TOP_* sections - Both URL path and filename are updated together * fix(hooks): run ruff only on staged Python files in pre-commit The backend section was running ruff on ALL Python files in apps/backend/ and then staging ALL Python files, which caused unstaged changes to be unintentionally committed. Now it mirrors the frontend's lint-staged approach by only processing files that are actually staged for commit. * fix(pr-review): block merge when CI checks are failing PR reviews now check GitHub CI status and treat failing checks as blocking issues. Previously, the review could approve a PR even when tests were failing, leading to bad UX where contributors would fix code issues only to discover CI failures afterward. Changes: - Add get_pr_checks() method to gh_client for fetching CI status - Integrate CI status into verdict logic for initial and follow-up reviews - Show CI failures in "Blocking Issues" section alongside code findings - Override "Ready to Merge" verdict to "Blocked" when CI is failing πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(security): add tool input validation and fix qa_reviewer permissions Addresses two issues identified in agent logs: 1. QA reviewer was missing write permissions to create qa_report.md and update implementation_plan.json. Changed qa_reviewer tools config from BASE_READ_TOOLS + ["Bash"] to include BASE_WRITE_TOOLS. 2. Malformed tool inputs (None, wrong type) caused confusing errors like "Command 'Category' is not in the allowed commands". Added validation in bash_security_hook to block malformed inputs with clear error messages. Also created centralized tool_input_validator.py and updated all session processors (session.py, qa/reviewer.py, qa/fixer.py, agent_runner.py) to use get_safe_tool_input() helper for safe extraction. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(pr-review): add finding-validator agent to prevent false positives PR follow-up reviews were keeping findings as "unresolved" without re-investigating if they were valid issues. Initial false positives (hallucinated issues) would persist indefinitely across follow-ups. This adds a new finding-validator specialist agent that: - Actively reads code at finding locations with fresh eyes - Requires concrete code evidence for any conclusion - Can dismiss findings as false_positive OR confirm them as valid - Integrates with the parallel follow-up review orchestrator Changes: - New pr_finding_validator.md prompt for the specialist agent - FindingValidationResult Pydantic model with evidence requirements - Validation fields on PRReviewFinding (status, evidence, confidence) - Updated orchestrator to invoke finding-validator for unresolved findings - Summary now shows dismissed false positives count - 17 new tests covering validation scenarios πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(pr-review): keep GitHubPRs mounted to preserve background task state When navigating away from the GitHub PRs tab during a background PR review or follow-up, the component would unmount and lose visibility of the running process. Applied the same pattern used by TerminalGrid: keep the component always mounted but hidden with CSS when not active. This ensures the Zustand store subscriptions remain active and both the PR list and detail views update correctly during background reviews. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(pr-review): fix phase status badges and list sync issues Two issues fixed: 1. PR list not showing 'Ready for Follow-up' indicator - Changed from using imperative store updates to React hook subscriptions for setNewCommitsCheck, ensuring proper re-renders when store updates. 2. Phase status badges showing 'Complete' incorrectly during review - Only mark phases as completed if they were actually active (had entries). Save immediately when phase becomes active. Added frontend defensive check to show 'Pending' for completed phases with no entries during streaming. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(release): sync versions and add PowerShell newline escaping Address PR review findings: - Sync root package.json and backend __init__.py to 2.7.2-beta.12 to match frontend version (fixes atomic versioning violation) - Add \r and \n escaping to escapePowerShellCommand() to prevent newline injection attacks in Windows terminal commands πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 7210610 commit 8e5c11a

30 files changed

Lines changed: 1319 additions & 154 deletions

β€Ž.github/workflows/pr-status-gate.ymlβ€Ž

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: PR Status Gate
22

33
on:
44
workflow_run:
5-
workflows: [CI, Lint, Quality Security, CLA Assistant, Quality Commit Lint]
5+
workflows: [CI, Lint, Quality Security]
66
types: [completed]
77

88
permissions:
@@ -36,7 +36,7 @@ jobs:
3636
// To find check names: Go to PR β†’ Checks tab β†’ copy exact name
3737
// To update: Edit this list when workflow jobs are added/renamed/removed
3838
//
39-
// Last validated: 2025-12-26
39+
// Last validated: 2025-12-31
4040
// ═══════════════════════════════════════════════════════════════════════
4141
const requiredChecks = [
4242
// CI workflow (ci.yml) - 3 checks
@@ -49,11 +49,7 @@ jobs:
4949
'Quality Security / CodeQL (javascript-typescript) (pull_request)',
5050
'Quality Security / CodeQL (python) (pull_request)',
5151
'Quality Security / Python Security (Bandit) (pull_request)',
52-
'Quality Security / Security Summary (pull_request)',
53-
// CLA Assistant workflow (cla.yml) - 1 check
54-
'CLA Assistant / CLA Check',
55-
// Quality Commit Lint workflow (quality-commit-lint.yml) - 1 check
56-
'Quality Commit Lint / Conventional Commits (pull_request)'
52+
'Quality Security / Security Summary (pull_request)'
5753
];
5854
5955
const statusLabels = {

β€Ž.husky/pre-commitβ€Ž

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,44 @@ if git diff --cached --name-only | grep -q "^package.json$"; then
3636
echo " Updated apps/backend/__init__.py to $VERSION"
3737
fi
3838

39-
# Sync to README.md
39+
# Sync to README.md - section-aware updates (stable vs beta)
4040
if [ -f "README.md" ]; then
4141
# Escape hyphens for shields.io badge format (shields.io uses -- for literal hyphens)
4242
ESCAPED_VERSION=$(echo "$VERSION" | sed 's/-/--/g')
43-
# Update version badge - match both stable (X.Y.Z) and prerelease (X.Y.Z-prerelease.N or X.Y.Z--prerelease.N)
44-
sed -i.bak "s/version-[0-9]*\.[0-9]*\.[0-9]*\(-\{1,2\}[a-z]*\.[0-9]*\)*-blue/version-$ESCAPED_VERSION-blue/g" README.md
45-
# Update download links - match both stable and prerelease versions
46-
sed -i.bak "s/Auto-Claude-[0-9]*\.[0-9]*\.[0-9]*\(-[a-z]*\.[0-9]*\)*/Auto-Claude-$VERSION/g" README.md
43+
44+
# Detect if this is a prerelease (contains - after base version, e.g., 2.7.2-beta.10)
45+
if echo "$VERSION" | grep -q '-'; then
46+
# PRERELEASE: Update only beta sections
47+
echo " Detected PRERELEASE version: $VERSION"
48+
49+
# Update beta version badge (orange)
50+
sed -i.bak "s/beta-[0-9]*\.[0-9]*\.[0-9]*\(--[a-z]*\.[0-9]*\)*-orange/beta-$ESCAPED_VERSION-orange/g" README.md
51+
52+
# Update beta version badge link (within BETA_VERSION_BADGE section)
53+
sed -i.bak '/<!-- BETA_VERSION_BADGE -->/,/<!-- BETA_VERSION_BADGE_END -->/s|releases/tag/v[0-9.a-z-]*)|releases/tag/v'"$VERSION"')|g' README.md
54+
55+
# Update beta download links (within BETA_DOWNLOADS section only)
56+
for SUFFIX in "win32-x64.exe" "darwin-arm64.dmg" "darwin-x64.dmg" "linux-x86_64.AppImage" "linux-amd64.deb" "linux-x86_64.flatpak"; do
57+
sed -i.bak '/<!-- BETA_DOWNLOADS -->/,/<!-- BETA_DOWNLOADS_END -->/{s|Auto-Claude-[0-9.a-z-]*-'"$SUFFIX"'](https://github.com/AndyMik90/Auto-Claude/releases/download/v[^/]*/Auto-Claude-[^)]*-'"$SUFFIX"')|Auto-Claude-'"$VERSION"'-'"$SUFFIX"'](https://github.com/AndyMik90/Auto-Claude/releases/download/v'"$VERSION"'/Auto-Claude-'"$VERSION"'-'"$SUFFIX"')|g}' README.md
58+
done
59+
else
60+
# STABLE: Update stable sections and top badge
61+
echo " Detected STABLE version: $VERSION"
62+
63+
# Update top version badge (blue) - within TOP_VERSION_BADGE section
64+
sed -i.bak '/<!-- TOP_VERSION_BADGE -->/,/<!-- TOP_VERSION_BADGE_END -->/s/version-[0-9]*\.[0-9]*\.[0-9]*\(--[a-z]*\.[0-9]*\)*-blue/version-'"$ESCAPED_VERSION"'-blue/g' README.md
65+
sed -i.bak '/<!-- TOP_VERSION_BADGE -->/,/<!-- TOP_VERSION_BADGE_END -->/s|releases/tag/v[0-9.a-z-]*)|releases/tag/v'"$VERSION"')|g' README.md
66+
67+
# Update stable version badge (blue) - within STABLE_VERSION_BADGE section
68+
sed -i.bak '/<!-- STABLE_VERSION_BADGE -->/,/<!-- STABLE_VERSION_BADGE_END -->/s/stable-[0-9]*\.[0-9]*\.[0-9]*\(--[a-z]*\.[0-9]*\)*-blue/stable-'"$ESCAPED_VERSION"'-blue/g' README.md
69+
sed -i.bak '/<!-- STABLE_VERSION_BADGE -->/,/<!-- STABLE_VERSION_BADGE_END -->/s|releases/tag/v[0-9.a-z-]*)|releases/tag/v'"$VERSION"')|g' README.md
70+
71+
# Update stable download links (within STABLE_DOWNLOADS section only)
72+
for SUFFIX in "win32-x64.exe" "darwin-arm64.dmg" "darwin-x64.dmg" "linux-x86_64.AppImage" "linux-amd64.deb"; do
73+
sed -i.bak '/<!-- STABLE_DOWNLOADS -->/,/<!-- STABLE_DOWNLOADS_END -->/{s|Auto-Claude-[0-9.a-z-]*-'"$SUFFIX"'](https://github.com/AndyMik90/Auto-Claude/releases/download/v[^/]*/Auto-Claude-[^)]*-'"$SUFFIX"')|Auto-Claude-'"$VERSION"'-'"$SUFFIX"'](https://github.com/AndyMik90/Auto-Claude/releases/download/v'"$VERSION"'/Auto-Claude-'"$VERSION"'-'"$SUFFIX"')|g}' README.md
74+
done
75+
fi
76+
4777
rm -f README.md.bak
4878
git add README.md
4979
echo " Updated README.md to $VERSION"
@@ -72,20 +102,25 @@ if git diff --cached --name-only | grep -q "^apps/backend/.*\.py$"; then
72102
fi
73103

74104
if [ -n "$RUFF" ]; then
75-
# Run ruff linting (auto-fix)
76-
echo "Running ruff lint..."
77-
$RUFF check apps/backend/ --fix
78-
if [ $? -ne 0 ]; then
79-
echo "Ruff lint failed. Please fix Python linting errors before committing."
80-
exit 1
105+
# Get only staged Python files in apps/backend (process only what's being committed)
106+
STAGED_PY_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep "^apps/backend/.*\.py$" || true)
107+
108+
if [ -n "$STAGED_PY_FILES" ]; then
109+
# Run ruff linting (auto-fix) only on staged files
110+
echo "Running ruff lint on staged files..."
111+
echo "$STAGED_PY_FILES" | xargs $RUFF check --fix
112+
if [ $? -ne 0 ]; then
113+
echo "Ruff lint failed. Please fix Python linting errors before committing."
114+
exit 1
115+
fi
116+
117+
# Run ruff format (auto-fix) only on staged files
118+
echo "Running ruff format on staged files..."
119+
echo "$STAGED_PY_FILES" | xargs $RUFF format
120+
121+
# Re-stage only the files that were originally staged (in case ruff modified them)
122+
echo "$STAGED_PY_FILES" | xargs git add
81123
fi
82-
83-
# Run ruff format (auto-fix)
84-
echo "Running ruff format..."
85-
$RUFF format apps/backend/
86-
87-
# Stage any files that were auto-fixed by ruff (POSIX-compliant)
88-
find apps/backend -name "*.py" -type f -exec git add {} + 2>/dev/null || true
89124
else
90125
echo "Warning: ruff not found, skipping Python linting. Install with: uv pip install ruff"
91126
fi

β€Ž.pre-commit-config.yamlβ€Ž

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,41 @@ repos:
2525
# Sync to apps/backend/__init__.py
2626
sed -i.bak "s/__version__ = \"[^\"]*\"/__version__ = \"$VERSION\"/" apps/backend/__init__.py && rm -f apps/backend/__init__.py.bak
2727
28-
# Sync to README.md - shields.io version badge (text and URL)
28+
# Sync to README.md - section-aware updates (stable vs beta)
2929
ESCAPED_VERSION=$(echo "$VERSION" | sed 's/-/--/g')
30-
sed -i.bak -e "s/version-[0-9]*\.[0-9]*\.[0-9]*\(-\{1,2\}[a-z]*\.[0-9]*\)*-blue/version-$ESCAPED_VERSION-blue/g" -e "s|releases/tag/v[0-9.a-z-]*)|releases/tag/v$VERSION)|g" README.md
3130
32-
# Sync to README.md - download links with correct filenames and URLs
33-
for SUFFIX in "win32-x64.exe" "darwin-arm64.dmg" "darwin-x64.dmg" "linux-x86_64.AppImage" "linux-amd64.deb"; do
34-
sed -i.bak "s|Auto-Claude-[0-9.a-z-]*-${SUFFIX}](https://github.com/AndyMik90/Auto-Claude/releases/download/v[^/]*/Auto-Claude-[^)]*-${SUFFIX})|Auto-Claude-${VERSION}-${SUFFIX}](https://github.com/AndyMik90/Auto-Claude/releases/download/v${VERSION}/Auto-Claude-${VERSION}-${SUFFIX})|g" README.md
35-
done
31+
# Detect if this is a prerelease (contains - after base version)
32+
if echo "$VERSION" | grep -q '-'; then
33+
# PRERELEASE: Update only beta sections
34+
echo " Detected PRERELEASE version: $VERSION"
35+
36+
# Update beta version badge (orange)
37+
sed -i.bak "s/beta-[0-9]*\.[0-9]*\.[0-9]*\(--[a-z]*\.[0-9]*\)*-orange/beta-$ESCAPED_VERSION-orange/g" README.md
38+
39+
# Update beta version badge link
40+
sed -i.bak '/<!-- BETA_VERSION_BADGE -->/,/<!-- BETA_VERSION_BADGE_END -->/s|releases/tag/v[0-9.a-z-]*)|releases/tag/v'"$VERSION"')|g' README.md
41+
42+
# Update beta download links (within BETA_DOWNLOADS section only)
43+
for SUFFIX in "win32-x64.exe" "darwin-arm64.dmg" "darwin-x64.dmg" "linux-x86_64.AppImage" "linux-amd64.deb" "linux-x86_64.flatpak"; do
44+
sed -i.bak '/<!-- BETA_DOWNLOADS -->/,/<!-- BETA_DOWNLOADS_END -->/{s|Auto-Claude-[0-9.a-z-]*-'"$SUFFIX"'](https://github.com/AndyMik90/Auto-Claude/releases/download/v[^/]*/Auto-Claude-[^)]*-'"$SUFFIX"')|Auto-Claude-'"$VERSION"'-'"$SUFFIX"'](https://github.com/AndyMik90/Auto-Claude/releases/download/v'"$VERSION"'/Auto-Claude-'"$VERSION"'-'"$SUFFIX"')|g}' README.md
45+
done
46+
else
47+
# STABLE: Update stable sections and top badge
48+
echo " Detected STABLE version: $VERSION"
49+
50+
# Update top version badge (blue)
51+
sed -i.bak '/<!-- TOP_VERSION_BADGE -->/,/<!-- TOP_VERSION_BADGE_END -->/s/version-[0-9]*\.[0-9]*\.[0-9]*\(--[a-z]*\.[0-9]*\)*-blue/version-'"$ESCAPED_VERSION"'-blue/g' README.md
52+
sed -i.bak '/<!-- TOP_VERSION_BADGE -->/,/<!-- TOP_VERSION_BADGE_END -->/s|releases/tag/v[0-9.a-z-]*)|releases/tag/v'"$VERSION"')|g' README.md
53+
54+
# Update stable version badge (blue)
55+
sed -i.bak '/<!-- STABLE_VERSION_BADGE -->/,/<!-- STABLE_VERSION_BADGE_END -->/s/stable-[0-9]*\.[0-9]*\.[0-9]*\(--[a-z]*\.[0-9]*\)*-blue/stable-'"$ESCAPED_VERSION"'-blue/g' README.md
56+
sed -i.bak '/<!-- STABLE_VERSION_BADGE -->/,/<!-- STABLE_VERSION_BADGE_END -->/s|releases/tag/v[0-9.a-z-]*)|releases/tag/v'"$VERSION"')|g' README.md
57+
58+
# Update stable download links (within STABLE_DOWNLOADS section only)
59+
for SUFFIX in "win32-x64.exe" "darwin-arm64.dmg" "darwin-x64.dmg" "linux-x86_64.AppImage" "linux-amd64.deb"; do
60+
sed -i.bak '/<!-- STABLE_DOWNLOADS -->/,/<!-- STABLE_DOWNLOADS_END -->/{s|Auto-Claude-[0-9.a-z-]*-'"$SUFFIX"'](https://github.com/AndyMik90/Auto-Claude/releases/download/v[^/]*/Auto-Claude-[^)]*-'"$SUFFIX"')|Auto-Claude-'"$VERSION"'-'"$SUFFIX"'](https://github.com/AndyMik90/Auto-Claude/releases/download/v'"$VERSION"'/Auto-Claude-'"$VERSION"'-'"$SUFFIX"')|g}' README.md
61+
done
62+
fi
3663
rm -f README.md.bak
3764
3865
# Stage changes

β€Žapps/backend/__init__.pyβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@
1919
See README.md for full documentation.
2020
"""
2121

22-
__version__ = "2.7.2-beta.10"
22+
__version__ = "2.7.2-beta.12"
2323
__author__ = "Auto Claude Team"

β€Žapps/backend/agents/session.pyβ€Ž

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
is_build_complete,
2222
)
2323
from recovery import RecoveryManager
24+
from security.tool_input_validator import get_safe_tool_input
2425
from task_logger import (
2526
LogEntryType,
2627
LogPhase,
@@ -386,41 +387,43 @@ async def run_agent_session(
386387
)
387388
elif block_type == "ToolUseBlock" and hasattr(block, "name"):
388389
tool_name = block.name
389-
tool_input = None
390+
tool_input_display = None
390391
tool_count += 1
391392

393+
# Safely extract tool input (handles None, non-dict, etc.)
394+
inp = get_safe_tool_input(block)
395+
392396
# Extract meaningful tool input for display
393-
if hasattr(block, "input") and block.input:
394-
inp = block.input
395-
if isinstance(inp, dict):
396-
if "pattern" in inp:
397-
tool_input = f"pattern: {inp['pattern']}"
398-
elif "file_path" in inp:
399-
fp = inp["file_path"]
400-
if len(fp) > 50:
401-
fp = "..." + fp[-47:]
402-
tool_input = fp
403-
elif "command" in inp:
404-
cmd = inp["command"]
405-
if len(cmd) > 50:
406-
cmd = cmd[:47] + "..."
407-
tool_input = cmd
408-
elif "path" in inp:
409-
tool_input = inp["path"]
397+
if inp:
398+
if "pattern" in inp:
399+
tool_input_display = f"pattern: {inp['pattern']}"
400+
elif "file_path" in inp:
401+
fp = inp["file_path"]
402+
if len(fp) > 50:
403+
fp = "..." + fp[-47:]
404+
tool_input_display = fp
405+
elif "command" in inp:
406+
cmd = inp["command"]
407+
if len(cmd) > 50:
408+
cmd = cmd[:47] + "..."
409+
tool_input_display = cmd
410+
elif "path" in inp:
411+
tool_input_display = inp["path"]
410412

411413
debug(
412414
"session",
413415
f"Tool call #{tool_count}: {tool_name}",
414-
tool_input=tool_input,
415-
full_input=str(block.input)[:500]
416-
if hasattr(block, "input")
417-
else None,
416+
tool_input=tool_input_display,
417+
full_input=str(inp)[:500] if inp else None,
418418
)
419419

420420
# Log tool start (handles printing too)
421421
if task_logger:
422422
task_logger.tool_start(
423-
tool_name, tool_input, phase, print_to_console=True
423+
tool_name,
424+
tool_input_display,
425+
phase,
426+
print_to_console=True,
424427
)
425428
else:
426429
print(f"\n[Tool: {tool_name}]", flush=True)

β€Žapps/backend/agents/tools_pkg/models.pyβ€Ž

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,9 @@ def is_electron_mcp_enabled() -> bool:
216216
# QA PHASES (Read + test + browser + Graphiti memory)
217217
# ═══════════════════════════════════════════════════════════════════════
218218
"qa_reviewer": {
219-
# Read-only + Bash (for running tests) - reviewer should NOT edit code
220-
"tools": BASE_READ_TOOLS + ["Bash"] + WEB_TOOLS,
219+
# Read + Write/Edit (for QA reports and plan updates) + Bash (for tests)
220+
# Note: Reviewer writes to spec directory only (qa_report.md, implementation_plan.json)
221+
"tools": BASE_READ_TOOLS + BASE_WRITE_TOOLS + WEB_TOOLS,
221222
"mcp_servers": ["context7", "graphiti", "auto-claude", "browser"],
222223
"mcp_servers_optional": ["linear"], # For updating issue status
223224
"auto_claude_tools": [

0 commit comments

Comments
Β (0)