diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index a60e63df..0e06e2ea 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -56,8 +56,8 @@ body:
label: Component
description: Which part of Auto Claude is affected?
options:
- - Python Backend (auto-claude/)
- - Electron UI (auto-claude-ui/)
+ - Python Backend (apps/backend/)
+ - Electron UI (apps/frontend/)
- Both
- Not sure
validations:
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index 1ab14837..2cb0f656 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -38,8 +38,8 @@ body:
label: Component
description: Which part of Auto Claude would this affect?
options:
- - Python Backend (auto-claude/)
- - Electron UI (auto-claude-ui/)
+ - Python Backend (apps/backend/)
+ - Electron UI (apps/frontend/)
- Both
- New component
- Not sure
diff --git a/.github/workflows/build-prebuilds.yml b/.github/workflows/build-prebuilds.yml
index 34765831..d3d4585a 100644
--- a/.github/workflows/build-prebuilds.yml
+++ b/.github/workflows/build-prebuilds.yml
@@ -32,22 +32,17 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
- node-version: '20'
-
- - name: Setup pnpm
- uses: pnpm/action-setup@v4
- with:
- version: 9
+ node-version: '24'
- name: Install Visual Studio Build Tools
uses: microsoft/setup-msbuild@v2
- name: Install node-pty and rebuild for Electron
- working-directory: auto-claude-ui
+ working-directory: apps/frontend
shell: pwsh
run: |
# Install only node-pty
- pnpm add node-pty@1.1.0-beta42
+ npm install node-pty@1.1.0-beta42
# Get Electron ABI version
$electronAbi = (npx electron-abi $env:ELECTRON_VERSION)
@@ -57,7 +52,7 @@ jobs:
npx @electron/rebuild --version $env:ELECTRON_VERSION --module-dir node_modules/node-pty --arch ${{ matrix.arch }}
- name: Package prebuilt binaries
- working-directory: auto-claude-ui
+ working-directory: apps/frontend
shell: pwsh
run: |
$electronAbi = (npx electron-abi $env:ELECTRON_VERSION)
@@ -83,7 +78,7 @@ jobs:
Get-ChildItem $prebuildDir
- name: Create archive
- working-directory: auto-claude-ui
+ working-directory: apps/frontend
shell: pwsh
run: |
$electronAbi = (npx electron-abi $env:ELECTRON_VERSION)
@@ -98,14 +93,14 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: node-pty-win32-${{ matrix.arch }}
- path: auto-claude-ui/node-pty-*.zip
+ path: apps/frontend/node-pty-*.zip
retention-days: 90
- name: Upload to release
if: github.event_name == 'release'
uses: softprops/action-gh-release@v1
with:
- files: auto-claude-ui/node-pty-*.zip
+ files: apps/frontend/node-pty-*.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 76b644a7..cb036c59 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,30 +29,34 @@ jobs:
version: "latest"
- name: Install dependencies
- working-directory: auto-claude
+ working-directory: apps/backend
run: |
uv venv
uv pip install -r requirements.txt
- uv pip install -r ../tests/requirements-test.txt
+ uv pip install -r ../../tests/requirements-test.txt
- name: Run tests
- working-directory: auto-claude
+ working-directory: apps/backend
+ env:
+ PYTHONPATH: ${{ github.workspace }}/apps/backend
run: |
source .venv/bin/activate
- pytest ../tests/ -v --tb=short -x
+ pytest ../../tests/ -v --tb=short -x
- name: Run tests with coverage
if: matrix.python-version == '3.12'
- working-directory: auto-claude
+ working-directory: apps/backend
+ env:
+ PYTHONPATH: ${{ github.workspace }}/apps/backend
run: |
source .venv/bin/activate
- pytest ../tests/ -v --cov=. --cov-report=xml --cov-report=term-missing
+ pytest ../../tests/ -v --cov=. --cov-report=xml --cov-report=term-missing
- name: Upload coverage reports
if: matrix.python-version == '3.12'
uses: codecov/codecov-action@v4
with:
- file: ./auto-claude/coverage.xml
+ file: ./apps/backend/coverage.xml
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
@@ -67,39 +71,34 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
- node-version: '20'
+ node-version: '24'
- - name: Setup pnpm
- uses: pnpm/action-setup@v4
- with:
- version: 10
-
- - name: Get pnpm store directory
- id: pnpm-cache
- run: echo "dir=$(pnpm store path)" >> "$GITHUB_OUTPUT"
+ - name: Get npm cache directory
+ id: npm-cache
+ run: echo "dir=$(npm config get cache)" >> "$GITHUB_OUTPUT"
- uses: actions/cache@v4
with:
- path: ${{ steps.pnpm-cache.outputs.dir }}
- key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
- restore-keys: ${{ runner.os }}-pnpm-
+ path: ${{ steps.npm-cache.outputs.dir }}
+ key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
- working-directory: auto-claude-ui
- run: pnpm install --frozen-lockfile --ignore-scripts
+ working-directory: apps/frontend
+ run: npm ci --ignore-scripts
- name: Lint
- working-directory: auto-claude-ui
- run: pnpm run lint
+ working-directory: apps/frontend
+ run: npm run lint
- name: Type check
- working-directory: auto-claude-ui
- run: pnpm run typecheck
+ working-directory: apps/frontend
+ run: npm run typecheck
- name: Run tests
- working-directory: auto-claude-ui
- run: pnpm run test
+ working-directory: apps/frontend
+ run: npm run test
- name: Build
- working-directory: auto-claude-ui
- run: pnpm run build
+ working-directory: apps/frontend
+ run: npm run build
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 5a3b2581..76ad2e01 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -23,10 +23,10 @@ jobs:
run: pip install ruff
- name: Run ruff check
- run: ruff check auto-claude/ --output-format=github
+ run: ruff check apps/backend/ --output-format=github
- name: Run ruff format check
- run: ruff format auto-claude/ --check --diff
+ run: ruff format apps/backend/ --check --diff
# TypeScript/React linting
frontend:
@@ -38,21 +38,16 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
- node-version: '20'
-
- - name: Setup pnpm
- uses: pnpm/action-setup@v4
- with:
- version: 9
+ node-version: '24'
- name: Install dependencies
- working-directory: auto-claude-ui
- run: pnpm install --frozen-lockfile --ignore-scripts
+ working-directory: apps/frontend
+ run: npm ci --ignore-scripts
- name: Run ESLint
- working-directory: auto-claude-ui
- run: pnpm lint
+ working-directory: apps/frontend
+ run: npm run lint
- name: Run TypeScript check
- working-directory: auto-claude-ui
- run: pnpm typecheck
+ working-directory: apps/frontend
+ run: npm run typecheck
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index c02d7c89..1a4fe504 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,31 +23,26 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
- node-version: '20'
+ node-version: '24'
- - name: Setup pnpm
- uses: pnpm/action-setup@v4
- with:
- version: 10
-
- - name: Get pnpm store directory
- id: pnpm-cache
- run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT
+ - name: Get npm cache directory
+ id: npm-cache
+ run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
- path: ${{ steps.pnpm-cache.outputs.dir }}
- key: ${{ runner.os }}-x64-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
- restore-keys: ${{ runner.os }}-x64-pnpm-
+ path: ${{ steps.npm-cache.outputs.dir }}
+ key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
- run: cd auto-claude-ui && pnpm install --frozen-lockfile
+ run: cd apps/frontend && npm ci
- name: Build application
- run: cd auto-claude-ui && pnpm run build
+ run: cd apps/frontend && npm run build
- name: Package macOS (Intel)
- run: cd auto-claude-ui && pnpm run package:mac -- --arch=x64
+ run: cd apps/frontend && npm run package:mac -- --arch=x64
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.MAC_CERTIFICATE }}
@@ -63,7 +58,7 @@ jobs:
echo "Skipping notarization: APPLE_ID not configured"
exit 0
fi
- cd auto-claude-ui
+ cd apps/frontend
for dmg in dist/*.dmg; do
echo "Notarizing $dmg..."
xcrun notarytool submit "$dmg" \
@@ -80,8 +75,8 @@ jobs:
with:
name: macos-intel-builds
path: |
- auto-claude-ui/dist/*.dmg
- auto-claude-ui/dist/*.zip
+ apps/frontend/dist/*.dmg
+ apps/frontend/dist/*.zip
# Apple Silicon build on ARM64 runner for native compilation
build-macos-arm64:
@@ -92,31 +87,26 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
- node-version: '20'
+ node-version: '24'
- - name: Setup pnpm
- uses: pnpm/action-setup@v4
- with:
- version: 10
-
- - name: Get pnpm store directory
- id: pnpm-cache
- run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT
+ - name: Get npm cache directory
+ id: npm-cache
+ run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
- path: ${{ steps.pnpm-cache.outputs.dir }}
- key: ${{ runner.os }}-arm64-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
- restore-keys: ${{ runner.os }}-arm64-pnpm-
+ path: ${{ steps.npm-cache.outputs.dir }}
+ key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
- run: cd auto-claude-ui && pnpm install --frozen-lockfile
+ run: cd apps/frontend && npm ci
- name: Build application
- run: cd auto-claude-ui && pnpm run build
+ run: cd apps/frontend && npm run build
- name: Package macOS (Apple Silicon)
- run: cd auto-claude-ui && pnpm run package:mac -- --arch=arm64
+ run: cd apps/frontend && npm run package:mac -- --arch=arm64
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.MAC_CERTIFICATE }}
@@ -132,7 +122,7 @@ jobs:
echo "Skipping notarization: APPLE_ID not configured"
exit 0
fi
- cd auto-claude-ui
+ cd apps/frontend
for dmg in dist/*.dmg; do
echo "Notarizing $dmg..."
xcrun notarytool submit "$dmg" \
@@ -149,8 +139,8 @@ jobs:
with:
name: macos-arm64-builds
path: |
- auto-claude-ui/dist/*.dmg
- auto-claude-ui/dist/*.zip
+ apps/frontend/dist/*.dmg
+ apps/frontend/dist/*.zip
build-windows:
runs-on: windows-latest
@@ -160,32 +150,27 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
- node-version: '20'
+ node-version: '24'
- - name: Setup pnpm
- uses: pnpm/action-setup@v4
- with:
- version: 10
-
- - name: Get pnpm store directory
- id: pnpm-cache
+ - name: Get npm cache directory
+ id: npm-cache
shell: bash
- run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT
+ run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
- path: ${{ steps.pnpm-cache.outputs.dir }}
- key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
- restore-keys: ${{ runner.os }}-pnpm-
+ path: ${{ steps.npm-cache.outputs.dir }}
+ key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
- run: cd auto-claude-ui && pnpm install --frozen-lockfile
+ run: cd apps/frontend && npm ci
- name: Build application
- run: cd auto-claude-ui && pnpm run build
+ run: cd apps/frontend && npm run build
- name: Package Windows
- run: cd auto-claude-ui && pnpm run package:win
+ run: cd apps/frontend && npm run package:win
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.WIN_CERTIFICATE }}
@@ -196,7 +181,7 @@ jobs:
with:
name: windows-builds
path: |
- auto-claude-ui/dist/*.exe
+ apps/frontend/dist/*.exe
build-linux:
runs-on: ubuntu-latest
@@ -206,31 +191,26 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
- node-version: '20'
+ node-version: '24'
- - name: Setup pnpm
- uses: pnpm/action-setup@v4
- with:
- version: 10
-
- - name: Get pnpm store directory
- id: pnpm-cache
- run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT
+ - name: Get npm cache directory
+ id: npm-cache
+ run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
- path: ${{ steps.pnpm-cache.outputs.dir }}
- key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
- restore-keys: ${{ runner.os }}-pnpm-
+ path: ${{ steps.npm-cache.outputs.dir }}
+ key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: ${{ runner.os }}-npm-
- name: Install dependencies
- run: cd auto-claude-ui && pnpm install --frozen-lockfile
+ run: cd apps/frontend && npm ci
- name: Build application
- run: cd auto-claude-ui && pnpm run build
+ run: cd apps/frontend && npm run build
- name: Package Linux
- run: cd auto-claude-ui && pnpm run package:linux
+ run: cd apps/frontend && npm run package:linux
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -239,8 +219,8 @@ jobs:
with:
name: linux-builds
path: |
- auto-claude-ui/dist/*.AppImage
- auto-claude-ui/dist/*.deb
+ apps/frontend/dist/*.AppImage
+ apps/frontend/dist/*.deb
create-release:
needs: [build-macos-intel, build-macos-arm64, build-windows, build-linux]
diff --git a/.github/workflows/test-on-tag.yml b/.github/workflows/test-on-tag.yml
index 078bd561..f633c868 100644
--- a/.github/workflows/test-on-tag.yml
+++ b/.github/workflows/test-on-tag.yml
@@ -28,17 +28,19 @@ jobs:
version: "latest"
- name: Install dependencies
- working-directory: auto-claude
+ working-directory: apps/backend
run: |
uv venv
uv pip install -r requirements.txt
- uv pip install -r ../tests/requirements-test.txt
+ uv pip install -r ../../tests/requirements-test.txt
- name: Run tests
- working-directory: auto-claude
+ working-directory: apps/backend
+ env:
+ PYTHONPATH: ${{ github.workspace }}/apps/backend
run: |
source .venv/bin/activate
- pytest ../tests/ -v --tb=short
+ pytest ../../tests/ -v --tb=short
# Frontend tests
test-frontend:
@@ -50,17 +52,12 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
- node-version: '20'
-
- - name: Setup pnpm
- uses: pnpm/action-setup@v4
- with:
- version: 9
+ node-version: '24'
- name: Install dependencies
- working-directory: auto-claude-ui
- run: pnpm install --frozen-lockfile --ignore-scripts
+ working-directory: apps/frontend
+ run: npm ci --ignore-scripts
- name: Run tests
- working-directory: auto-claude-ui
- run: pnpm test
+ working-directory: apps/frontend
+ run: npm run test
diff --git a/.github/workflows/validate-version.yml b/.github/workflows/validate-version.yml
index b97fe71e..a076114d 100644
--- a/.github/workflows/validate-version.yml
+++ b/.github/workflows/validate-version.yml
@@ -26,7 +26,7 @@ jobs:
id: package_version
run: |
# Read version from package.json
- PACKAGE_VERSION=$(node -p "require('./auto-claude-ui/package.json').version")
+ PACKAGE_VERSION=$(node -p "require('./apps/frontend/package.json').version")
echo "version=$PACKAGE_VERSION" >> $GITHUB_OUTPUT
echo "Package.json version: $PACKAGE_VERSION"
diff --git a/.gitignore b/.gitignore
index 0781d8a0..7ba9c4ac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,31 +1,69 @@
-# OS
+# ===========================
+# OS Files
+# ===========================
.DS_Store
+.DS_Store?
+._*
Thumbs.db
+ehthumbs.db
+Desktop.ini
-# Environment files (contain API keys)
+# ===========================
+# Security - Environment & Secrets
+# ===========================
.env
-.env.local
+.env.*
+!.env.example
+*.pem
+*.key
+*.crt
+*.p12
+*.pfx
+.secrets
+secrets/
+credentials/
-# Git worktrees (used by auto-build parallel mode)
-.worktrees/
-
-# IDE
+# ===========================
+# IDE & Editors
+# ===========================
.idea/
.vscode/
*.swp
*.swo
+*.sublime-workspace
+*.sublime-project
+.project
+.classpath
+.settings/
+# ===========================
# Logs
+# ===========================
logs/
*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
-# Personal notes
-OPUS_ANALYSIS_AND_IDEAS.md
+# ===========================
+# Git Worktrees (parallel builds)
+# ===========================
+.worktrees/
-# Documentation
-docs/
+# ===========================
+# Auto Claude Generated
+# ===========================
+.auto-claude/
+.auto-build-security.json
+.auto-claude-security.json
+.auto-claude-status
+.claude_settings.json
+.update-metadata.json
-# Python
+# ===========================
+# Python (apps/backend)
+# ===========================
__pycache__/
*.py[cod]
*$py.class
@@ -33,25 +71,19 @@ __pycache__/
.Python
build/
develop-eggs/
-dist/
-downloads/
eggs/
.eggs/
-/lib/
-/lib64/
-parts/
-sdist/
-var/
-wheels/
*.egg-info/
.installed.cfg
*.egg
+MANIFEST
# Virtual environments
.venv/
venv/
ENV/
env/
+.conda/
# Testing
.pytest_cache/
@@ -64,26 +96,69 @@ coverage.xml
*.py,cover
.hypothesis/
-# mypy
+# Type checking
.mypy_cache/
.dmypy.json
dmypy.json
+.pytype/
+.pyre/
-# Auto-build generated files
-.auto-build-security.json
-.auto-claude-security.json
-.auto-claude-status
-.claude_settings.json
-.update-metadata.json
+# ===========================
+# Node.js (apps/frontend)
+# ===========================
+node_modules/
+.npm
+.yarn/
+.pnp.*
-# Development of Auto Build with Auto Build
+# Build output
+dist/
+out/
+*.tsbuildinfo
+
+# Cache
+.cache/
+.parcel-cache/
+.turbo/
+.eslintcache
+.prettiercache
+
+# ===========================
+# Electron
+# ===========================
+apps/frontend/dist/
+apps/frontend/out/
+*.asar
+*.blockmap
+*.snap
+*.deb
+*.rpm
+*.AppImage
+*.dmg
+*.exe
+*.msi
+
+# ===========================
+# Testing
+# ===========================
+coverage/
+.nyc_output/
+test-results/
+playwright-report/
+playwright/.cache/
+
+# ===========================
+# Misc
+# ===========================
+*.local
+*.bak
+*.tmp
+*.temp
+
+# Development
dev/
-
-.auto-claude/
-
+_bmad/
+_bmad-output/
+.claude/
/docs
-
-_bmad
-_bmad-output
-
-.claude
+OPUS_ANALYSIS_AND_IDEAS.md
diff --git a/.husky/commit-msg b/.husky/commit-msg
new file mode 100644
index 00000000..53d141b8
--- /dev/null
+++ b/.husky/commit-msg
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+# Commit message validation
+# Enforces conventional commit format: type(scope): description
+#
+# Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
+# Examples:
+# feat(tasks): add drag and drop support
+# fix(terminal): resolve scroll position issue
+# docs: update README with setup instructions
+# chore: update dependencies
+
+commit_msg_file=$1
+commit_msg=$(cat "$commit_msg_file")
+
+# Regex for conventional commits
+# Format: type(optional-scope): description
+pattern="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-z0-9-]+\))?: .{1,100}$"
+
+# Allow merge commits
+if echo "$commit_msg" | grep -qE "^Merge "; then
+ exit 0
+fi
+
+# Allow revert commits
+if echo "$commit_msg" | grep -qE "^Revert "; then
+ exit 0
+fi
+
+# Check first line against pattern
+first_line=$(echo "$commit_msg" | head -n 1)
+
+if ! echo "$first_line" | grep -qE "$pattern"; then
+ echo ""
+ echo "ERROR: Invalid commit message format!"
+ echo ""
+ echo "Your message: $first_line"
+ echo ""
+ echo "Expected format: type(scope): description"
+ echo ""
+ echo "Valid types:"
+ echo " feat - A new feature"
+ echo " fix - A bug fix"
+ echo " docs - Documentation changes"
+ echo " style - Code style changes (formatting, semicolons, etc.)"
+ echo " refactor - Code refactoring (no feature/fix)"
+ echo " perf - Performance improvements"
+ echo " test - Adding or updating tests"
+ echo " build - Build system or dependencies"
+ echo " ci - CI/CD configuration"
+ echo " chore - Other changes (maintenance)"
+ echo " revert - Reverting a previous commit"
+ echo ""
+ echo "Examples:"
+ echo " feat(tasks): add drag and drop support"
+ echo " fix(terminal): resolve scroll position issue"
+ echo " docs: update README"
+ echo " chore: update dependencies"
+ echo ""
+ exit 1
+fi
+
+# Check description length (max 100 chars for first line)
+if [ ${#first_line} -gt 100 ]; then
+ echo ""
+ echo "ERROR: Commit message first line is too long!"
+ echo "Maximum: 100 characters"
+ echo "Current: ${#first_line} characters"
+ echo ""
+ exit 1
+fi
+
+exit 0
diff --git a/.husky/pre-commit b/.husky/pre-commit
index d3f678b6..e79978be 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,6 +1,96 @@
#!/bin/sh
-# Run lint-staged in auto-claude-ui if there are staged files there
-if git diff --cached --name-only | grep -q "^auto-claude-ui/"; then
- cd auto-claude-ui && pnpm exec lint-staged
+echo "Running pre-commit checks..."
+
+# =============================================================================
+# BACKEND CHECKS (Python) - Run first, before frontend
+# =============================================================================
+
+# Check if there are staged Python files in apps/backend
+if git diff --cached --name-only | grep -q "^apps/backend/.*\.py$"; then
+ echo "Python changes detected, running backend checks..."
+
+ # Run ruff linting
+ echo "Running ruff lint..."
+ ruff check apps/backend/ --fix
+ if [ $? -ne 0 ]; then
+ echo "Ruff lint failed. Please fix Python linting errors before committing."
+ exit 1
+ fi
+
+ # Run ruff format check
+ echo "Running ruff format check..."
+ ruff format apps/backend/ --check
+ if [ $? -ne 0 ]; then
+ echo "Ruff format check failed. Run 'ruff format apps/backend/' to fix."
+ exit 1
+ fi
+
+ # Run pytest (skip slow/integration tests and Windows-incompatible tests for pre-commit speed)
+ echo "Running Python tests..."
+ cd apps/backend
+ # Tests to skip: graphiti (external deps), merge_file_tracker/service_orchestrator/worktree/workspace (Windows path/git issues)
+ IGNORE_TESTS="--ignore=../../tests/test_graphiti.py --ignore=../../tests/test_merge_file_tracker.py --ignore=../../tests/test_service_orchestrator.py --ignore=../../tests/test_worktree.py --ignore=../../tests/test_workspace.py"
+ if [ -d ".venv" ]; then
+ # Use venv if it exists
+ if [ -f ".venv/bin/pytest" ]; then
+ PYTHONPATH=. .venv/bin/pytest ../../tests/ -v --tb=short -x -m "not slow and not integration" $IGNORE_TESTS
+ elif [ -f ".venv/Scripts/pytest.exe" ]; then
+ # Windows
+ PYTHONPATH=. .venv/Scripts/pytest.exe ../../tests/ -v --tb=short -x -m "not slow and not integration" $IGNORE_TESTS
+ else
+ PYTHONPATH=. python -m pytest ../../tests/ -v --tb=short -x -m "not slow and not integration" $IGNORE_TESTS
+ fi
+ else
+ PYTHONPATH=. python -m pytest ../../tests/ -v --tb=short -x -m "not slow and not integration" $IGNORE_TESTS
+ fi
+ if [ $? -ne 0 ]; then
+ echo "Python tests failed. Please fix failing tests before committing."
+ exit 1
+ fi
+ cd ../..
+
+ echo "Backend checks passed!"
fi
+
+# =============================================================================
+# FRONTEND CHECKS (TypeScript/React)
+# =============================================================================
+
+# Check if there are staged files in apps/frontend
+if git diff --cached --name-only | grep -q "^apps/frontend/"; then
+ echo "Frontend changes detected, running frontend checks..."
+ cd apps/frontend
+
+ # Run lint-staged (handles staged .ts/.tsx files)
+ npm exec lint-staged
+
+ # Run TypeScript type check
+ echo "Running type check..."
+ npm run typecheck
+ if [ $? -ne 0 ]; then
+ echo "Type check failed. Please fix TypeScript errors before committing."
+ exit 1
+ fi
+
+ # Run linting
+ echo "Running lint..."
+ npm run lint
+ if [ $? -ne 0 ]; then
+ echo "Lint failed. Run 'npm run lint:fix' to auto-fix issues."
+ exit 1
+ fi
+
+ # Check for vulnerabilities (only high severity)
+ echo "Checking for vulnerabilities..."
+ npm audit --audit-level=high
+ if [ $? -ne 0 ]; then
+ echo "High severity vulnerabilities found. Run 'npm audit fix' to resolve."
+ exit 1
+ fi
+
+ cd ../..
+ echo "Frontend checks passed!"
+fi
+
+echo "All pre-commit checks passed!"
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 5ee8b74e..e167c1d6 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,29 +1,39 @@
repos:
- # Python linting (auto-claude/)
+ # Python linting (apps/backend/)
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.3
hooks:
- id: ruff
args: [--fix]
- files: ^auto-claude/
+ files: ^apps/backend/
- id: ruff-format
- files: ^auto-claude/
+ files: ^apps/backend/
- # Frontend linting (auto-claude-ui/)
+ # Python tests (apps/backend/) - skip slow/integration tests for pre-commit speed
+ - repo: local
+ hooks:
+ - id: pytest
+ name: Python Tests
+ entry: bash -c 'cd apps/backend && PYTHONPATH=. python -m pytest ../../tests/ -v --tb=short -x -m "not slow and not integration" --ignore=../../tests/test_graphiti.py'
+ language: system
+ files: ^(apps/backend/.*\.py$|tests/.*\.py$)
+ pass_filenames: false
+
+ # Frontend linting (apps/frontend/)
- repo: local
hooks:
- id: eslint
name: ESLint
- entry: bash -c 'cd auto-claude-ui && pnpm lint'
+ entry: bash -c 'cd apps/frontend && npm run lint'
language: system
- files: ^auto-claude-ui/.*\.(ts|tsx|js|jsx)$
+ files: ^apps/frontend/.*\.(ts|tsx|js|jsx)$
pass_filenames: false
- id: typecheck
name: TypeScript Check
- entry: bash -c 'cd auto-claude-ui && pnpm typecheck'
+ entry: bash -c 'cd apps/frontend && npm run typecheck'
language: system
- files: ^auto-claude-ui/.*\.(ts|tsx)$
+ files: ^apps/frontend/.*\.(ts|tsx)$
pass_filenames: false
# General checks
diff --git a/CLAUDE.md b/CLAUDE.md
index 67a50bca..58020759 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -9,89 +9,109 @@ Auto Claude is a multi-agent autonomous coding framework that builds software th
## Commands
### Setup
+
+**Requirements:**
+- Python 3.12+ (required for backend)
+- Node.js (for frontend)
+
```bash
-# Install dependencies (from auto-claude/)
-uv venv && uv pip install -r requirements.txt
-# Or: python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
+# Install all dependencies from root
+npm run install:all
+
+# Or install separately:
+# Backend (from apps/backend/)
+cd apps/backend && uv venv && uv pip install -r requirements.txt
+
+# Frontend (from apps/frontend/)
+cd apps/frontend && npm install
# Set up OAuth token
claude setup-token
-# Add to auto-claude/.env: CLAUDE_CODE_OAUTH_TOKEN=your-token
+# Add to apps/backend/.env: CLAUDE_CODE_OAUTH_TOKEN=your-token
```
### Creating and Running Specs
```bash
+cd apps/backend
+
# Create a spec interactively
-python auto-claude/spec_runner.py --interactive
+python spec_runner.py --interactive
# Create spec from task description
-python auto-claude/spec_runner.py --task "Add user authentication"
+python spec_runner.py --task "Add user authentication"
# Force complexity level (simple/standard/complex)
-python auto-claude/spec_runner.py --task "Fix button" --complexity simple
+python spec_runner.py --task "Fix button" --complexity simple
# Run autonomous build
-python auto-claude/run.py --spec 001
+python run.py --spec 001
# List all specs
-python auto-claude/run.py --list
+python run.py --list
```
### Workspace Management
```bash
+cd apps/backend
+
# Review changes in isolated worktree
-python auto-claude/run.py --spec 001 --review
+python run.py --spec 001 --review
# Merge completed build into project
-python auto-claude/run.py --spec 001 --merge
+python run.py --spec 001 --merge
# Discard build
-python auto-claude/run.py --spec 001 --discard
+python run.py --spec 001 --discard
```
### QA Validation
```bash
+cd apps/backend
+
# Run QA manually
-python auto-claude/run.py --spec 001 --qa
+python run.py --spec 001 --qa
# Check QA status
-python auto-claude/run.py --spec 001 --qa-status
+python run.py --spec 001 --qa-status
```
### Testing
```bash
# Install test dependencies (required first time)
-cd auto-claude && uv pip install -r ../tests/requirements-test.txt
+cd apps/backend && uv pip install -r ../../tests/requirements-test.txt
# Run all tests (use virtual environment pytest)
-auto-claude/.venv/bin/pytest tests/ -v
+apps/backend/.venv/bin/pytest tests/ -v
# Run single test file
-auto-claude/.venv/bin/pytest tests/test_security.py -v
+apps/backend/.venv/bin/pytest tests/test_security.py -v
# Run specific test
-auto-claude/.venv/bin/pytest tests/test_security.py::test_bash_command_validation -v
+apps/backend/.venv/bin/pytest tests/test_security.py::test_bash_command_validation -v
# Skip slow tests
-auto-claude/.venv/bin/pytest tests/ -m "not slow"
+apps/backend/.venv/bin/pytest tests/ -m "not slow"
+
+# Or from root
+npm run test:backend
```
### Spec Validation
```bash
-python auto-claude/validate_spec.py --spec-dir auto-claude/specs/001-feature --checkpoint all
+python apps/backend/validate_spec.py --spec-dir apps/backend/specs/001-feature --checkpoint all
```
### Releases
```bash
# Automated version bump and release (recommended)
-node scripts/bump-version.js patch # 2.5.5 -> 2.5.6
-node scripts/bump-version.js minor # 2.5.5 -> 2.6.0
-node scripts/bump-version.js major # 2.5.5 -> 3.0.0
-node scripts/bump-version.js 2.6.0 # Set specific version
+node scripts/bump-version.js patch # 2.8.0 -> 2.8.1
+node scripts/bump-version.js minor # 2.8.0 -> 2.9.0
+node scripts/bump-version.js major # 2.8.0 -> 3.0.0
+node scripts/bump-version.js 2.9.0 # Set specific version
# Then push to trigger GitHub release workflows
git push origin main
-git push origin v2.6.0
+git push origin v2.9.0
```
See [RELEASE.md](RELEASE.md) for detailed release process documentation.
@@ -111,18 +131,18 @@ See [RELEASE.md](RELEASE.md) for detailed release process documentation.
3. QA Reviewer validates acceptance criteria
4. QA Fixer resolves issues in a loop
-### Key Components
+### Key Components (apps/backend/)
- **client.py** - Claude SDK client with security hooks and tool permissions
- **security.py** + **project_analyzer.py** - Dynamic command allowlisting based on detected project stack
- **worktree.py** - Git worktree isolation for safe feature development
- **memory.py** - File-based session memory (primary, always-available storage)
-- **graphiti_memory.py** - Optional graph-based cross-session memory with semantic search
+- **graphiti_memory.py** - Graph-based cross-session memory with semantic search
- **graphiti_providers.py** - Multi-provider factory for Graphiti (OpenAI, Anthropic, Azure, Ollama, Google AI)
- **graphiti_config.py** - Configuration and validation for Graphiti integration
- **linear_updater.py** - Optional Linear integration for progress tracking
-### Agent Prompts (auto-claude/prompts/)
+### Agent Prompts (apps/backend/prompts/)
| Prompt | Purpose |
|--------|---------|
@@ -139,7 +159,7 @@ See [RELEASE.md](RELEASE.md) for detailed release process documentation.
### Spec Directory Structure
-Each spec in `auto-claude/specs/XXX-name/` contains:
+Each spec in `.auto-claude/specs/XXX-name/` contains:
- `spec.md` - Feature specification
- `requirements.json` - Structured user requirements
- `context.json` - Discovered codebase context
@@ -188,35 +208,36 @@ Dual-layer memory architecture:
- Human-readable files in `specs/XXX/memory/`
- Session insights, patterns, gotchas, codebase map
-**Graphiti Memory (Optional Enhancement)** - `graphiti_memory.py`
+**Graphiti Memory** - `graphiti_memory.py`
- Graph database with semantic search (LadybugDB - embedded, no Docker)
- Cross-session context retrieval
-- Requires Python 3.12+
- Multi-provider support:
- LLM: OpenAI, Anthropic, Azure OpenAI, Ollama, Google AI (Gemini)
- Embedders: OpenAI, Voyage AI, Azure OpenAI, Ollama, Google AI
-
-```bash
-# Setup (requires Python 3.12+)
-pip install real_ladybug graphiti-core
-```
-
-Enable with: `GRAPHITI_ENABLED=true` + provider credentials. See `.env.example`.
+- Configure with provider credentials in `.env.example`
## Project Structure
-Auto Claude can be used in two ways:
-
-**As a standalone CLI tool** (original project):
-```bash
-python auto-claude/run.py --spec 001
+```
+auto-claude/
+├── apps/
+│ ├── backend/ # Python backend/CLI (the framework code)
+│ └── frontend/ # Electron desktop UI
+├── guides/ # Documentation
+├── tests/ # Test suite
+└── scripts/ # Build and utility scripts
```
-**With the optional Electron frontend** (`auto-claude-ui/`):
-- Provides a GUI for task management and progress tracking
-- Wraps the CLI commands - the backend works independently
+**As a standalone CLI tool**:
+```bash
+cd apps/backend
+python run.py --spec 001
+```
+
+**With the Electron frontend**:
+```bash
+npm start # Build and run desktop app
+npm run dev # Run in development mode
+```
-**Directory layout:**
-- `auto-claude/` - Python backend/CLI (the framework code)
-- `auto-claude-ui/` - Optional Electron frontend
- `.auto-claude/specs/` - Per-project data (specs, plans, QA reports) - gitignored
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ef53d5f9..4b64cf42 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,6 +5,7 @@ Thank you for your interest in contributing to Auto Claude! This document provid
## Table of Contents
- [Prerequisites](#prerequisites)
+- [Quick Start](#quick-start)
- [Development Setup](#development-setup)
- [Python Backend](#python-backend)
- [Electron Frontend](#electron-frontend)
@@ -30,37 +31,77 @@ Thank you for your interest in contributing to Auto Claude! This document provid
Before contributing, ensure you have the following installed:
-- **Python 3.8+** - For the backend framework
-- **Node.js 18+** - For the Electron frontend
-- **pnpm** - Package manager for the frontend (`npm install -g pnpm`)
+- **Python 3.12+** - For the backend framework
+- **Node.js 24+** - For the Electron frontend
+- **npm 10+** - Package manager for the frontend (comes with Node.js)
- **uv** (recommended) or **pip** - Python package manager
- **Git** - Version control
+### Installing Python 3.12
+
+**Windows:**
+```bash
+winget install Python.Python.3.12
+```
+
+**macOS:**
+```bash
+brew install python@3.12
+```
+
+**Linux (Ubuntu/Debian):**
+```bash
+sudo apt install python3.12 python3.12-venv
+```
+
+## Quick Start
+
+The fastest way to get started:
+
+```bash
+# Clone the repository
+git clone https://github.com/AndyMik90/Auto-Claude.git
+cd Auto-Claude
+
+# Install all dependencies (cross-platform)
+npm run install:all
+
+# Run in development mode
+npm run dev
+
+# Or build and run production
+npm start
+```
+
## Development Setup
The project consists of two main components:
-1. **Python Backend** (`auto-claude/`) - The core autonomous coding framework
-2. **Electron Frontend** (`auto-claude-ui/`) - Optional desktop UI
+1. **Python Backend** (`apps/backend/`) - The core autonomous coding framework
+2. **Electron Frontend** (`apps/frontend/`) - Optional desktop UI
### Python Backend
+The recommended way is to use `npm run install:backend`, but you can also set up manually:
+
```bash
-# Navigate to the auto-claude directory
-cd auto-claude
+# Navigate to the backend directory
+cd apps/backend
-# Create virtual environment (using uv - recommended)
-uv venv
-source .venv/bin/activate # On Windows: .venv\Scripts\activate
-uv pip install -r requirements.txt
+# Create virtual environment
+# Windows:
+py -3.12 -m venv .venv
+.venv\Scripts\activate
-# Or using standard Python
-python3 -m venv .venv
+# macOS/Linux:
+python3.12 -m venv .venv
source .venv/bin/activate
+
+# Install dependencies
pip install -r requirements.txt
# Install test dependencies
-pip install -r ../tests/requirements-test.txt
+pip install -r ../../tests/requirements-test.txt
# Set up environment
cp .env.example .env
@@ -70,31 +111,31 @@ cp .env.example .env
### Electron Frontend
```bash
-# Navigate to the UI directory
-cd auto-claude-ui
+# Navigate to the frontend directory
+cd apps/frontend
# Install dependencies
-pnpm install
+npm install
# Start development server
-pnpm dev
+npm run dev
# Build for production
-pnpm build
+npm run build
# Package for distribution
-pnpm package
+npm run package
```
## Running from Source
If you want to run Auto Claude from source (for development or testing unreleased features), follow these steps:
-### Step 1: Clone and Set Up Python Backend
+### Step 1: Clone and Set Up
```bash
git clone https://github.com/AndyMik90/Auto-Claude.git
-cd Auto-Claude/auto-claude
+cd Auto-Claude/apps/backend
# Using uv (recommended)
uv venv && uv pip install -r requirements.txt
@@ -105,6 +146,7 @@ source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -r requirements.txt
# Set up environment
+cd apps/backend
cp .env.example .env
# Edit .env and add your CLAUDE_CODE_OAUTH_TOKEN (get it via: claude setup-token)
```
@@ -112,16 +154,16 @@ cp .env.example .env
### Step 2: Run the Desktop UI
```bash
-cd ../auto-claude-ui
+cd ../frontend
# Install dependencies
-pnpm install
+npm install
# Development mode (hot reload)
-pnpm dev
+npm run dev
# Or production build
-pnpm run build && pnpm run start
+npm run build && npm run start
```
@@ -132,7 +174,7 @@ Auto Claude automatically downloads prebuilt binaries for Windows. If prebuilts
1. Download [Visual Studio Build Tools 2022](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
2. Select "Desktop development with C++" workload
3. In "Individual Components", add "MSVC v143 - VS 2022 C++ x64/x86 Spectre-mitigated libs"
-4. Restart terminal and run `pnpm install` again
+4. Restart terminal and run `npm install` again
@@ -158,10 +200,10 @@ When you commit, the following checks run automatically:
| Check | Scope | Description |
|-------|-------|-------------|
-| **ruff** | `auto-claude/` | Python linter with auto-fix |
-| **ruff-format** | `auto-claude/` | Python code formatter |
-| **eslint** | `auto-claude-ui/` | TypeScript/React linter |
-| **typecheck** | `auto-claude-ui/` | TypeScript type checking |
+| **ruff** | `apps/backend/` | Python linter with auto-fix |
+| **ruff-format** | `apps/backend/` | Python code formatter |
+| **eslint** | `apps/frontend/` | TypeScript/React linter |
+| **typecheck** | `apps/frontend/` | TypeScript type checking |
| **trailing-whitespace** | All files | Removes trailing whitespace |
| **end-of-file-fixer** | All files | Ensures files end with newline |
| **check-yaml** | All files | Validates YAML syntax |
@@ -218,7 +260,7 @@ def gnc(sd):
### TypeScript/React
- Use TypeScript strict mode
-- Follow the existing component patterns in `auto-claude-ui/src/`
+- Follow the existing component patterns in `apps/frontend/src/`
- Use functional components with hooks
- Prefer named exports over default exports
- Use the UI components from `src/renderer/components/ui/`
@@ -248,20 +290,25 @@ export default function(props) {
### Python Tests
```bash
-# Run all tests
-pytest tests/ -v
+# Run all tests (from repository root)
+npm run test:backend
+
+# Or manually with pytest
+cd apps/backend
+.venv/Scripts/pytest.exe ../tests -v # Windows
+.venv/bin/pytest ../tests -v # macOS/Linux
# Run a specific test file
-pytest tests/test_security.py -v
+npm run test:backend -- tests/test_security.py -v
# Run a specific test
-pytest tests/test_security.py::test_bash_command_validation -v
+npm run test:backend -- tests/test_security.py::test_bash_command_validation -v
# Skip slow tests
-pytest tests/ -m "not slow"
+npm run test:backend -- -m "not slow"
# Run with coverage
-pytest tests/ --cov=auto-claude --cov-report=html
+pytest tests/ --cov=apps/backend --cov-report=html
```
Test configuration is in `tests/pytest.ini`.
@@ -269,26 +316,26 @@ Test configuration is in `tests/pytest.ini`.
### Frontend Tests
```bash
-cd auto-claude-ui
+cd apps/frontend
# Run unit tests
-pnpm test
+npm test
# Run tests in watch mode
-pnpm test:watch
+npm run test:watch
# Run with coverage
-pnpm test:coverage
+npm run test:coverage
# Run E2E tests (requires built app)
-pnpm build
-pnpm test:e2e
+npm run build
+npm run test:e2e
# Run linting
-pnpm lint
+npm run lint
# Run type checking
-pnpm typecheck
+npm run typecheck
```
### Testing Requirements
@@ -326,15 +373,15 @@ Before a PR can be merged:
```bash
# Python tests
-cd auto-claude
+cd apps/backend
source .venv/bin/activate
-pytest ../tests/ -v
+pytest ../../tests/ -v
# Frontend tests
-cd auto-claude-ui
-pnpm test
-pnpm lint
-pnpm typecheck
+cd apps/frontend
+npm test
+npm run lint
+npm run typecheck
```
## Git Workflow
@@ -378,6 +425,7 @@ Use descriptive branch names with a prefix indicating the type of change:
|--------|---------|---------|
| `feature/` | New feature | `feature/add-dark-mode` |
| `fix/` | Bug fix | `fix/memory-leak-in-worker` |
+| `hotfix/` | Urgent production fix | `hotfix/critical-crash-fix` |
| `docs/` | Documentation | `docs/update-readme` |
| `refactor/` | Code refactoring | `refactor/simplify-auth-flow` |
| `test/` | Test additions/fixes | `test/add-integration-tests` |
@@ -443,6 +491,52 @@ git branch -d release/v2.8.0
git push origin --delete release/v2.8.0
```
+### Hotfix Workflow
+
+For urgent production fixes that can't wait for the normal release cycle:
+
+**1. Create hotfix from main**
+
+```bash
+git checkout main
+git pull origin main
+git checkout -b hotfix/150-critical-fix
+```
+
+**2. Fix the issue**
+
+```bash
+# ... make changes ...
+git commit -m "hotfix: fix critical crash on startup"
+```
+
+**3. Open PR to main (fast-track review)**
+
+```bash
+gh pr create --base main --title "hotfix: fix critical crash on startup"
+```
+
+**4. After merge to main, sync to develop**
+
+```bash
+git checkout develop
+git pull origin develop
+git merge main
+git push origin develop
+```
+
+```
+main ─────●─────●─────●─────●───── (production)
+ ↑ ↑ ↑ ↑
+develop ──●─────●─────●─────●───── (integration)
+ ↑ ↑ ↑
+feature/123 ────●
+feature/124 ──────────●
+hotfix/125 ─────────────────●───── (from main, merge to both)
+```
+
+> **Note:** Hotfixes branch FROM `main` and merge TO `main` first, then sync back to `develop` to keep branches aligned.
+
### Commit Messages
Write clear, concise commit messages that explain the "why" behind changes:
@@ -487,11 +581,11 @@ git commit -m "WIP"
3. **Test thoroughly**:
```bash
- # Python
- pytest tests/ -v
+ # Python (from repository root)
+ npm run test:backend
# Frontend
- cd auto-claude-ui && pnpm test && pnpm lint && pnpm typecheck
+ cd apps/frontend && npm test && npm run lint && npm run typecheck
```
4. **Update documentation** if your changes affect:
@@ -550,7 +644,7 @@ When requesting a feature:
Auto Claude consists of two main parts:
-### Python Backend (`auto-claude/`)
+### Python Backend (`apps/backend/`)
The core autonomous coding framework:
@@ -560,9 +654,9 @@ The core autonomous coding framework:
- **Memory**: `memory.py` (file-based), `graphiti_memory.py` (graph-based)
- **QA**: `qa_loop.py`, `prompts/qa_*.md`
-### Electron Frontend (`auto-claude-ui/`)
+### Electron Frontend (`apps/frontend/`)
-Optional desktop interface:
+Desktop interface:
- **Main Process**: `src/main/` - Electron main process, IPC handlers
- **Renderer**: `src/renderer/` - React UI components
diff --git a/README.md b/README.md
index 7dbd0a46..b6ea25f9 100644
--- a/README.md
+++ b/README.md
@@ -1,269 +1,222 @@
# Auto Claude
-Your AI coding companion. Build features, fix bugs, and ship faster — with autonomous agents that plan, code, and validate for you.
+**Autonomous multi-agent coding framework that plans, builds, and validates software for you.**

-[](https://discord.gg/KCXaPBr4Dj)
+[](https://github.com/AndyMik90/Auto-Claude/releases/latest)
+[](./agpl-3.0.txt)
+[](https://discord.gg/KCXaPBr4Dj)
+[](https://github.com/AndyMik90/Auto-Claude/actions)
-## What It Does ✨
+---
-**Auto Claude is a desktop app that supercharges your AI coding workflow.** Whether you're a vibe coder just getting started or an experienced developer, Auto Claude meets you where you are.
+## Download
-- **Autonomous Tasks** — Describe what you want to build, and agents handle planning, coding, and validation while you focus on other work
-- **Agent Terminals** — Run Claude Code in up to 12 terminals with a clean layout, smart naming based on context, and one-click task context injection
-- **Safe by Default** — All work happens in git worktrees, keeping your main branch undisturbed until you're ready to merge
-- **Self-Validating** — Built-in QA agents check their own work before you review
+Get the latest pre-built release for your platform:
-**The result?** 10x your output while maintaining code quality.
+| Platform | Download | Notes |
+|----------|----------|-------|
+| **Windows** | [Auto-Claude-2.8.0.exe](https://github.com/AndyMik90/Auto-Claude/releases/latest) | Installer (NSIS) |
+| **macOS (Apple Silicon)** | [Auto-Claude-2.8.0-arm64.dmg](https://github.com/AndyMik90/Auto-Claude/releases/latest) | M1/M2/M3 Macs |
+| **macOS (Intel)** | [Auto-Claude-2.8.0-x64.dmg](https://github.com/AndyMik90/Auto-Claude/releases/latest) | Intel Macs |
+| **Linux** | [Auto-Claude-2.8.0.AppImage](https://github.com/AndyMik90/Auto-Claude/releases/latest) | Universal |
+| **Linux (Debian)** | [Auto-Claude-2.8.0.deb](https://github.com/AndyMik90/Auto-Claude/releases/latest) | Ubuntu/Debian |
-## Key Features
+> All releases include SHA256 checksums and VirusTotal scan results for security verification.
-- **Parallel Agents**: Run multiple builds simultaneously while you focus on other work
-- **Context Engineering**: Agents understand your codebase structure before writing code
-- **Self-Validating**: Built-in QA loop catches issues before you review
-- **Isolated Workspaces**: All work happens in git worktrees — your code stays safe
-- **AI Merge Resolution**: Intelligent conflict resolution when merging back to main — no manual conflict fixing
-- **Cross-Platform**: Desktop app runs on Mac, Windows, and Linux
-- **Any Project Type**: Build web apps, APIs, CLIs — works with any software project
+---
+
+## Requirements
+
+- **Claude Pro/Max subscription** - [Get one here](https://claude.ai/upgrade)
+- **Claude Code CLI** - `npm install -g @anthropic-ai/claude-code`
+- **Git repository** - Your project must be initialized as a git repo
+- **Python 3.12+** - Required for the backend and Memory Layer
+
+---
## Quick Start
-### Download Auto Claude
-
-Download the latest release for your platform from [GitHub Releases](https://github.com/AndyMik90/Auto-Claude/releases/latest):
-
-| Platform | Download |
-|----------|----------|
-| **macOS (Apple Silicon M1-M4)** | `*-arm64.dmg` |
-| **macOS (Intel)** | `*-x64.dmg` |
-| **Windows** | `*.exe` |
-| **Linux** | `*.AppImage` or `*.deb` |
-
-> **Not sure which Mac?** Click the Apple menu () > "About This Mac". Look for "Chip" - M1/M2/M3/M4 = Apple Silicon, otherwise Intel.
-
-### Prerequisites
-
-Before using Auto Claude, you need:
-
-1. **Claude Subscription** - Requires [Claude Pro or Max](https://claude.ai/upgrade) for Claude Code access
-2. **Claude Code CLI** - Install with: `npm install -g @anthropic-ai/claude-code`
-
-### Install and Run
-
-1. **Download** the installer for your platform from the table above
-2. **Install**:
- - **macOS**: Open the `.dmg`, drag Auto Claude to Applications
- - **Windows**: Run the `.exe` installer (see note below about security warning)
- - **Linux**: Make the AppImage executable (`chmod +x`) and run it, or install the `.deb`
-3. **Launch** Auto Claude
-4. **Add your project** and start building!
-
-
-Windows users: Security warning when installing
-
-The Windows installer is not yet code-signed, so you may see a "Windows protected your PC" warning from Microsoft Defender SmartScreen.
-
-**To proceed:**
-1. Click "More info"
-2. Click "Run anyway"
-
-This is safe — all releases are automatically scanned with VirusTotal before publishing. You can verify any installer by checking the **VirusTotal Scan Results** section in each [release's notes](https://github.com/AndyMik90/Auto-Claude/releases).
-
-We're working on obtaining a code signing certificate for future releases.
-
-
-
-> **Want to build from source?** See [CONTRIBUTING.md](CONTRIBUTING.md#running-from-source) for development setup.
+1. **Download and install** the app for your platform
+2. **Open your project** - Select a git repository folder
+3. **Connect Claude** - The app will guide you through OAuth setup
+4. **Create a task** - Describe what you want to build
+5. **Watch it work** - Agents plan, code, and validate autonomously
---
-## 🎯 Features
+## Features
+
+| Feature | Description |
+|---------|-------------|
+| **Autonomous Tasks** | Describe your goal; agents handle planning, implementation, and validation |
+| **Parallel Execution** | Run multiple builds simultaneously with up to 12 agent terminals |
+| **Isolated Workspaces** | All changes happen in git worktrees - your main branch stays safe |
+| **Self-Validating QA** | Built-in quality assurance loop catches issues before you review |
+| **AI-Powered Merge** | Automatic conflict resolution when integrating back to main |
+| **Memory Layer** | Agents retain insights across sessions for smarter builds |
+| **Cross-Platform** | Native desktop apps for Windows, macOS, and Linux |
+| **Auto-Updates** | App updates automatically when new versions are released |
+
+---
+
+## Interface
### Kanban Board
-
-Plan tasks and let AI handle the planning, coding, and validation — all in a visual interface. Track progress from "Planning" to "Done" while agents work autonomously.
+Visual task management from planning through completion. Create tasks and monitor agent progress in real-time.
### Agent Terminals
+AI-powered terminals with one-click task context injection. Spawn multiple agents for parallel work.
-Spawn up to 12 AI-powered terminals for hands-on coding. Inject task context with a click, reference files from your project, and work rapidly across multiple sessions.
-
-**Power users:** Connect multiple Claude Code subscriptions to run even more agents in parallel — perfect for teams or heavy workloads.
-
-
-
-### Insights
-
-Have a conversation about your project in a ChatGPT-style interface. Ask questions, get explanations, and explore your codebase through natural dialogue.
+
### Roadmap
+AI-assisted feature planning with competitor analysis and audience targeting.
-Based on your target audience, AI anticipates and plans the most impactful features you should focus on. Prioritize what matters most to your users.
+
-
-
-### Ideation
-
-Let AI help you create a project that shines. Rapidly understand your codebase and discover:
-- Code improvements and refactoring opportunities
-- Performance bottlenecks
-- Security vulnerabilities
-- Documentation gaps
-- UI/UX enhancements
-- Overall code quality issues
-
-### Changelog
-
-Write professional changelogs effortlessly. Generate release notes from completed Auto Claude tasks or integrate with GitHub to create masterclass changelogs automatically.
-
-### Context
-
-See exactly what Auto Claude understands about your project — the tech stack, file structure, patterns, and insights it uses to write better code.
-
-### AI Merge Resolution
-
-When your main branch evolves while a build is in progress, Auto Claude automatically resolves merge conflicts using AI — no manual `<<<<<<< HEAD` fixing required.
-
-**How it works:**
-1. **Git Auto-Merge First** — Simple non-conflicting changes merge instantly without AI
-2. **Conflict-Only AI** — For actual conflicts, AI receives only the specific conflict regions (not entire files), achieving ~98% prompt reduction
-3. **Parallel Processing** — Multiple conflicting files resolve simultaneously for faster merges
-4. **Syntax Validation** — Every merge is validated before being applied
-
-**The result:** A build that was 50+ commits behind main merges in seconds instead of requiring manual conflict resolution.
+### Additional Features
+- **Insights** - Chat interface for exploring your codebase
+- **Ideation** - Discover improvements, performance issues, and vulnerabilities
+- **Changelog** - Generate release notes from completed tasks
---
-## CLI Usage (Terminal-Only)
-
-For terminal-based workflows, headless servers, or CI/CD integration, see **[guides/CLI-USAGE.md](guides/CLI-USAGE.md)**.
-
-## ⚙️ How It Works
-
-Auto Claude focuses on three core principles: **context engineering** (understanding your codebase before writing code), **good coding standards** (following best practices and patterns), and **validation logic** (ensuring code works before you see it).
-
-### The Agent Pipeline
-
-**Phase 1: Spec Creation** (3-8 phases based on complexity)
-
-Before any code is written, agents gather context and create a detailed specification:
-
-1. **Discovery** — Analyzes your project structure and tech stack
-2. **Requirements** — Gathers what you want to build through interactive conversation
-3. **Research** — Validates external integrations against real documentation
-4. **Context Discovery** — Finds relevant files in your codebase
-5. **Spec Writer** — Creates a comprehensive specification document
-6. **Spec Critic** — Self-critiques using extended thinking to find issues early
-7. **Planner** — Breaks work into subtasks with dependencies
-8. **Validation** — Ensures all outputs are valid before proceeding
-
-**Phase 2: Implementation**
-
-With a validated spec, coding agents execute the plan:
-
-1. **Planner Agent** — Creates subtask-based implementation plan
-2. **Coder Agent** — Implements subtasks one-by-one with verification
-3. **QA Reviewer** — Validates all acceptance criteria
-4. **QA Fixer** — Fixes issues in a self-healing loop (up to 50 iterations)
-
-Each session runs with a fresh context window. Progress is tracked via `implementation_plan.json` and Git commits.
-
-**Phase 3: Merge**
-
-When you're ready to merge, AI handles any conflicts that arose while you were working:
-
-1. **Conflict Detection** — Identifies files modified in both main and the build
-2. **3-Tier Resolution** — Git auto-merge → Conflict-only AI → Full-file AI (fallback)
-3. **Parallel Merge** — Multiple files resolve simultaneously
-4. **Staged for Review** — Changes are staged but not committed, so you can review before finalizing
-
-### 🔒 Security Model
-
-Three-layer defense keeps your code safe:
-- **OS Sandbox** — Bash commands run in isolation
-- **Filesystem Restrictions** — Operations limited to project directory
-- **Command Allowlist** — Only approved commands based on your project's stack
-
## Project Structure
```
-your-project/
-├── .worktrees/ # Created during build (git-ignored)
-│ └── auto-claude/ # Isolated workspace for AI coding
-├── .auto-claude/ # Per-project data (specs, plans, QA reports)
-│ ├── specs/ # Task specifications
-│ ├── roadmap/ # Project roadmap
-│ └── ideation/ # Ideas and planning
-├── auto-claude/ # Python backend (framework code)
-│ ├── run.py # Build entry point
-│ ├── spec_runner.py # Spec creation orchestrator
-│ ├── prompts/ # Agent prompt templates
-│ └── ...
-└── auto-claude-ui/ # Electron desktop application
- └── ...
+Auto-Claude/
+├── apps/
+│ ├── backend/ # Python agents, specs, QA pipeline
+│ └── frontend/ # Electron desktop application
+├── guides/ # Additional documentation
+├── tests/ # Test suite
+└── scripts/ # Build utilities
```
-### Understanding the Folders
+---
-**You don't create these folders manually** - they serve different purposes:
+## CLI Usage
-- **`auto-claude/`** - The framework repository itself (clone this once from GitHub)
-- **`.auto-claude/`** - Created automatically in YOUR project when you run Auto Claude (stores specs, plans, QA reports)
-- **`.worktrees/`** - Temporary isolated workspaces created during builds (git-ignored, deleted after merge)
+For headless operation, CI/CD integration, or terminal-only workflows:
-**When using Auto Claude on your project:**
```bash
-cd your-project/ # Your own project directory
-python /path/to/auto-claude/run.py --spec 001
-# Auto Claude creates .auto-claude/ automatically in your-project/
+cd apps/backend
+
+# Create a spec interactively
+python spec_runner.py --interactive
+
+# Run autonomous build
+python run.py --spec 001
+
+# Review and merge
+python run.py --spec 001 --review
+python run.py --spec 001 --merge
```
-**When developing Auto Claude itself:**
+See [guides/CLI-USAGE.md](guides/CLI-USAGE.md) for complete CLI documentation.
+
+---
+
+## Configuration
+
+Create `apps/backend/.env` from the example:
+
```bash
-git clone https://github.com/yourusername/auto-claude
-cd auto-claude/ # You're working in the framework repo
+cp apps/backend/.env.example apps/backend/.env
```
-The `.auto-claude/` directory is gitignored and project-specific - you'll have one per project you use Auto Claude on.
-
-## Environment Variables (CLI Only)
-
-> **Desktop UI users:** These are configured through the app settings — no manual setup needed.
-
| Variable | Required | Description |
|----------|----------|-------------|
| `CLAUDE_CODE_OAUTH_TOKEN` | Yes | OAuth token from `claude setup-token` |
-| `AUTO_BUILD_MODEL` | No | Model override (default: claude-opus-4-5-20251101) |
+| `GRAPHITI_ENABLED` | No | Enable Memory Layer for cross-session context |
+| `AUTO_BUILD_MODEL` | No | Override the default Claude model |
-See `auto-claude/.env.example` for complete configuration options.
+---
-## 💬 Community
+## Building from Source
-Join our Discord to get help, share what you're building, and connect with other Auto Claude users:
+For contributors and development:
-[](https://discord.gg/KCXaPBr4Dj)
+```bash
+# Clone the repository
+git clone https://github.com/AndyMik90/Auto-Claude.git
+cd Auto-Claude
-## 🤝 Contributing
+# Install all dependencies
+npm run install:all
-We welcome contributions! Whether it's bug fixes, new features, or documentation improvements.
+# Run in development mode
+npm run dev
-See **[CONTRIBUTING.md](CONTRIBUTING.md)** for guidelines on how to get started.
+# Or build and run
+npm start
+```
-## Acknowledgments
+**System requirements for building:**
+- Node.js 24+
+- Python 3.12+
+- npm 10+
-This framework was inspired by Anthropic's [Autonomous Coding Agent](https://github.com/anthropics/claude-quickstarts/tree/main/autonomous-coding). Thank you to the Anthropic team for their innovative work on autonomous coding systems.
+See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed development setup.
+
+---
+
+## Security
+
+Auto Claude uses a three-layer security model:
+
+1. **OS Sandbox** - Bash commands run in isolation
+2. **Filesystem Restrictions** - Operations limited to project directory
+3. **Dynamic Command Allowlist** - Only approved commands based on detected project stack
+
+All releases are:
+- Scanned with VirusTotal before publishing
+- Include SHA256 checksums for verification
+- Code-signed where applicable (macOS)
+
+---
+
+## Available Scripts
+
+| Command | Description |
+|---------|-------------|
+| `npm run install:all` | Install backend and frontend dependencies |
+| `npm start` | Build and run the desktop app |
+| `npm run dev` | Run in development mode with hot reload |
+| `npm run package` | Package for current platform |
+| `npm run package:mac` | Package for macOS |
+| `npm run package:win` | Package for Windows |
+| `npm run package:linux` | Package for Linux |
+| `npm run lint` | Run linter |
+| `npm test` | Run frontend tests |
+| `npm run test:backend` | Run backend tests |
+
+---
+
+## Contributing
+
+We welcome contributions! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for:
+- Development setup instructions
+- Code style guidelines
+- Testing requirements
+- Pull request process
+
+---
+
+## Community
+
+- **Discord** - [Join our community](https://discord.gg/KCXaPBr4Dj)
+- **Issues** - [Report bugs or request features](https://github.com/AndyMik90/Auto-Claude/issues)
+- **Discussions** - [Ask questions](https://github.com/AndyMik90/Auto-Claude/discussions)
+
+---
## License
**AGPL-3.0** - GNU Affero General Public License v3.0
-This software is licensed under AGPL-3.0, which means:
+Auto Claude is free to use. If you modify and distribute it, or run it as a service, your code must also be open source under AGPL-3.0.
-- **Attribution Required**: You must give appropriate credit, provide a link to the license, and indicate if changes were made. When using Auto Claude, please credit the project.
-- **Open Source Required**: If you modify this software and distribute it or run it as a service, you must release your source code under AGPL-3.0.
-- **Network Use (Copyleft)**: If you run this software as a network service (e.g., SaaS), users interacting with it over a network must be able to receive the source code.
-- **No Closed-Source Usage**: You cannot use this software in proprietary/closed-source projects without open-sourcing your entire project under AGPL-3.0.
-
-**In simple terms**: You can use Auto Claude freely, but if you build on it, your code must also be open source under AGPL-3.0 and attribute this project. Closed-source commercial use requires a separate license.
-
-For commercial licensing inquiries (closed-source usage), please contact the maintainers.
+Commercial licensing available for closed-source use cases.
diff --git a/RELEASE.md b/RELEASE.md
index 57914a06..3978b063 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -30,7 +30,7 @@ We provide an automated script that handles version bumping, git commits, and ta
```
This script will:
- - ✅ Update `auto-claude-ui/package.json` with the new version
+ - ✅ Update `apps/frontend/package.json` with the new version
- ✅ Create a git commit with the version change
- ✅ Create a git tag (e.g., `v2.5.6`)
- ⚠️ **NOT** push to remote (you control when to push)
@@ -71,7 +71,7 @@ We provide an automated script that handles version bumping, git commits, and ta
If you need to create a release manually, follow these steps **carefully** to avoid version mismatches:
-1. **Update `auto-claude-ui/package.json`:**
+1. **Update `apps/frontend/package.json`:**
```json
{
@@ -82,7 +82,7 @@ If you need to create a release manually, follow these steps **carefully** to av
2. **Commit the change:**
```bash
- git add auto-claude-ui/package.json
+ git add apps/frontend/package.json
git commit -m "chore: bump version to 2.5.6"
```
diff --git a/auto-claude/.env.example b/apps/backend/.env.example
similarity index 98%
rename from auto-claude/.env.example
rename to apps/backend/.env.example
index 8ce6af28..3d4233e2 100644
--- a/auto-claude/.env.example
+++ b/apps/backend/.env.example
@@ -117,9 +117,9 @@
# ELECTRON_DEBUG_PORT=9222
# =============================================================================
-# GRAPHITI MEMORY INTEGRATION (OPTIONAL)
+# GRAPHITI MEMORY INTEGRATION (REQUIRED)
# =============================================================================
-# Enable Graphiti-based persistent memory layer for cross-session context
+# Graphiti-based persistent memory layer for cross-session context
# retention. Uses LadybugDB as the embedded graph database.
#
# REQUIREMENTS:
@@ -133,8 +133,8 @@
# - Ollama (local, fully offline)
# - Google AI (Gemini)
-# Enable Graphiti integration (default: false)
-# GRAPHITI_ENABLED=true
+# Graphiti is enabled by default. Set to false to disable memory features.
+GRAPHITI_ENABLED=true
# =============================================================================
# GRAPHITI: Database Settings
diff --git a/auto-claude/.gitignore b/apps/backend/.gitignore
similarity index 94%
rename from auto-claude/.gitignore
rename to apps/backend/.gitignore
index 31e19add..ad10d960 100644
--- a/auto-claude/.gitignore
+++ b/apps/backend/.gitignore
@@ -61,3 +61,6 @@ Thumbs.db
# Tests (development only)
tests/
+
+# Auto Claude data directory
+.auto-claude/
diff --git a/apps/backend/README.md b/apps/backend/README.md
new file mode 100644
index 00000000..30640f61
--- /dev/null
+++ b/apps/backend/README.md
@@ -0,0 +1,120 @@
+# Auto Claude Backend
+
+Autonomous coding framework powered by Claude AI. Builds software features through coordinated multi-agent sessions.
+
+## Getting Started
+
+### 1. Install
+
+```bash
+cd apps/backend
+python -m pip install -r requirements.txt
+```
+
+### 2. Configure
+
+```bash
+cp .env.example .env
+```
+
+Set your Claude API token in `.env`:
+```
+CLAUDE_CODE_OAUTH_TOKEN=your-token-here
+```
+
+Get your token by running: `claude setup-token`
+
+### 3. Run
+
+```bash
+# List available specs
+python run.py --list
+
+# Run a spec
+python run.py --spec 001
+```
+
+## Requirements
+
+- Python 3.10+
+- Claude API token
+
+## Commands
+
+| Command | Description |
+|---------|-------------|
+| `--list` | List all specs |
+| `--spec 001` | Run spec 001 |
+| `--spec 001 --isolated` | Run in isolated workspace |
+| `--spec 001 --direct` | Run directly in repo |
+| `--spec 001 --merge` | Merge completed build |
+| `--spec 001 --review` | Review build changes |
+| `--spec 001 --discard` | Discard build |
+| `--spec 001 --qa` | Run QA validation |
+| `--list-worktrees` | List all worktrees |
+| `--help` | Show all options |
+
+## Configuration
+
+Optional `.env` settings:
+
+| Variable | Description |
+|----------|-------------|
+| `AUTO_BUILD_MODEL` | Override Claude model |
+| `DEBUG=true` | Enable debug logging |
+| `LINEAR_API_KEY` | Enable Linear integration |
+| `GRAPHITI_ENABLED=true` | Enable memory system |
+
+## Troubleshooting
+
+**"tree-sitter not available"** - Safe to ignore, uses regex fallback.
+
+**Missing module errors** - Run `python -m pip install -r requirements.txt`
+
+**Debug mode** - Set `DEBUG=true DEBUG_LEVEL=2` before running.
+
+---
+
+## For Developers
+
+### Project Structure
+
+```
+backend/
+├── agents/ # AI agent execution
+├── analysis/ # Code analysis
+├── cli/ # Command-line interface
+├── core/ # Core utilities
+├── integrations/ # External services (Linear, Graphiti)
+├── merge/ # Git merge handling
+├── project/ # Project detection
+├── prompts/ # Prompt templates
+├── qa/ # QA validation
+├── spec/ # Spec management
+└── ui/ # Terminal UI
+```
+
+### Design Principles
+
+- **SOLID** - Single responsibility, clean interfaces
+- **DRY** - Shared utilities in `core/`
+- **KISS** - Simple flat imports via facade modules
+
+### Import Convention
+
+```python
+# Use facade modules for clean imports
+from debug import debug, debug_error
+from progress import count_subtasks
+from workspace import setup_workspace
+```
+
+### Adding Features
+
+1. Create module in appropriate folder
+2. Export API in `__init__.py`
+3. Add facade module at root if commonly imported
+
+## License
+
+AGPL-3.0
diff --git a/apps/backend/__init__.py b/apps/backend/__init__.py
new file mode 100644
index 00000000..b67bca87
--- /dev/null
+++ b/apps/backend/__init__.py
@@ -0,0 +1,23 @@
+"""
+Auto Claude Backend - Autonomous Coding Framework
+==================================================
+
+Multi-agent autonomous coding framework that builds software through
+coordinated AI agent sessions.
+
+This package provides:
+- Autonomous agent execution for building features from specs
+- Workspace isolation via git worktrees
+- QA validation loops
+- Memory management (Graphiti + file-based)
+- Linear integration for project management
+
+Quick Start:
+ python run.py --spec 001 # Run a spec
+ python run.py --list # List all specs
+
+See README.md for full documentation.
+"""
+
+__version__ = "2.5.5"
+__author__ = "Auto Claude Team"
diff --git a/auto-claude/agent.py b/apps/backend/agent.py
similarity index 100%
rename from auto-claude/agent.py
rename to apps/backend/agent.py
diff --git a/auto-claude/agents/README.md b/apps/backend/agents/README.md
similarity index 100%
rename from auto-claude/agents/README.md
rename to apps/backend/agents/README.md
diff --git a/apps/backend/agents/__init__.py b/apps/backend/agents/__init__.py
new file mode 100644
index 00000000..37dae174
--- /dev/null
+++ b/apps/backend/agents/__init__.py
@@ -0,0 +1,92 @@
+"""
+Agents Module
+=============
+
+Modular agent system for autonomous coding.
+
+This module provides:
+- run_autonomous_agent: Main coder agent loop
+- run_followup_planner: Follow-up planner for completed specs
+- Memory management (Graphiti + file-based fallback)
+- Session management and post-processing
+- Utility functions for git and plan management
+
+Uses lazy imports to avoid circular dependencies.
+"""
+
+__all__ = [
+ # Main API
+ "run_autonomous_agent",
+ "run_followup_planner",
+ # Memory
+ "debug_memory_system_status",
+ "get_graphiti_context",
+ "save_session_memory",
+ "save_session_to_graphiti",
+ # Session
+ "run_agent_session",
+ "post_session_processing",
+ # Utils
+ "get_latest_commit",
+ "get_commit_count",
+ "load_implementation_plan",
+ "find_subtask_in_plan",
+ "find_phase_for_subtask",
+ "sync_plan_to_source",
+ # Constants
+ "AUTO_CONTINUE_DELAY_SECONDS",
+ "HUMAN_INTERVENTION_FILE",
+]
+
+
+def __getattr__(name):
+ """Lazy imports to avoid circular dependencies."""
+ if name in ("AUTO_CONTINUE_DELAY_SECONDS", "HUMAN_INTERVENTION_FILE"):
+ from .base import AUTO_CONTINUE_DELAY_SECONDS, HUMAN_INTERVENTION_FILE
+
+ return locals()[name]
+ elif name == "run_autonomous_agent":
+ from .coder import run_autonomous_agent
+
+ return run_autonomous_agent
+ elif name in (
+ "debug_memory_system_status",
+ "get_graphiti_context",
+ "save_session_memory",
+ "save_session_to_graphiti",
+ ):
+ from .memory_manager import (
+ debug_memory_system_status,
+ get_graphiti_context,
+ save_session_memory,
+ save_session_to_graphiti,
+ )
+
+ return locals()[name]
+ elif name == "run_followup_planner":
+ from .planner import run_followup_planner
+
+ return run_followup_planner
+ elif name in ("post_session_processing", "run_agent_session"):
+ from .session import post_session_processing, run_agent_session
+
+ return locals()[name]
+ elif name in (
+ "find_phase_for_subtask",
+ "find_subtask_in_plan",
+ "get_commit_count",
+ "get_latest_commit",
+ "load_implementation_plan",
+ "sync_plan_to_source",
+ ):
+ from .utils import (
+ find_phase_for_subtask,
+ find_subtask_in_plan,
+ get_commit_count,
+ get_latest_commit,
+ load_implementation_plan,
+ sync_plan_to_source,
+ )
+
+ return locals()[name]
+ raise AttributeError(f"module 'agents' has no attribute '{name}'")
diff --git a/auto-claude/agents/auto_claude_tools.py b/apps/backend/agents/auto_claude_tools.py
similarity index 100%
rename from auto-claude/agents/auto_claude_tools.py
rename to apps/backend/agents/auto_claude_tools.py
diff --git a/auto-claude/agents/base.py b/apps/backend/agents/base.py
similarity index 100%
rename from auto-claude/agents/base.py
rename to apps/backend/agents/base.py
diff --git a/auto-claude/agents/coder.py b/apps/backend/agents/coder.py
similarity index 100%
rename from auto-claude/agents/coder.py
rename to apps/backend/agents/coder.py
diff --git a/auto-claude/agents/memory_manager.py b/apps/backend/agents/memory_manager.py
similarity index 100%
rename from auto-claude/agents/memory_manager.py
rename to apps/backend/agents/memory_manager.py
diff --git a/auto-claude/agents/planner.py b/apps/backend/agents/planner.py
similarity index 100%
rename from auto-claude/agents/planner.py
rename to apps/backend/agents/planner.py
diff --git a/auto-claude/agents/session.py b/apps/backend/agents/session.py
similarity index 100%
rename from auto-claude/agents/session.py
rename to apps/backend/agents/session.py
diff --git a/auto-claude/agents/test_refactoring.py b/apps/backend/agents/test_refactoring.py
similarity index 100%
rename from auto-claude/agents/test_refactoring.py
rename to apps/backend/agents/test_refactoring.py
diff --git a/auto-claude/agents/tools_pkg/__init__.py b/apps/backend/agents/tools_pkg/__init__.py
similarity index 100%
rename from auto-claude/agents/tools_pkg/__init__.py
rename to apps/backend/agents/tools_pkg/__init__.py
diff --git a/auto-claude/agents/tools_pkg/models.py b/apps/backend/agents/tools_pkg/models.py
similarity index 100%
rename from auto-claude/agents/tools_pkg/models.py
rename to apps/backend/agents/tools_pkg/models.py
diff --git a/auto-claude/agents/tools_pkg/permissions.py b/apps/backend/agents/tools_pkg/permissions.py
similarity index 100%
rename from auto-claude/agents/tools_pkg/permissions.py
rename to apps/backend/agents/tools_pkg/permissions.py
diff --git a/auto-claude/agents/tools_pkg/registry.py b/apps/backend/agents/tools_pkg/registry.py
similarity index 100%
rename from auto-claude/agents/tools_pkg/registry.py
rename to apps/backend/agents/tools_pkg/registry.py
diff --git a/auto-claude/agents/tools_pkg/tools/__init__.py b/apps/backend/agents/tools_pkg/tools/__init__.py
similarity index 100%
rename from auto-claude/agents/tools_pkg/tools/__init__.py
rename to apps/backend/agents/tools_pkg/tools/__init__.py
diff --git a/auto-claude/agents/tools_pkg/tools/memory.py b/apps/backend/agents/tools_pkg/tools/memory.py
similarity index 100%
rename from auto-claude/agents/tools_pkg/tools/memory.py
rename to apps/backend/agents/tools_pkg/tools/memory.py
diff --git a/auto-claude/agents/tools_pkg/tools/progress.py b/apps/backend/agents/tools_pkg/tools/progress.py
similarity index 100%
rename from auto-claude/agents/tools_pkg/tools/progress.py
rename to apps/backend/agents/tools_pkg/tools/progress.py
diff --git a/auto-claude/agents/tools_pkg/tools/qa.py b/apps/backend/agents/tools_pkg/tools/qa.py
similarity index 100%
rename from auto-claude/agents/tools_pkg/tools/qa.py
rename to apps/backend/agents/tools_pkg/tools/qa.py
diff --git a/auto-claude/agents/tools_pkg/tools/subtask.py b/apps/backend/agents/tools_pkg/tools/subtask.py
similarity index 100%
rename from auto-claude/agents/tools_pkg/tools/subtask.py
rename to apps/backend/agents/tools_pkg/tools/subtask.py
diff --git a/auto-claude/agents/utils.py b/apps/backend/agents/utils.py
similarity index 100%
rename from auto-claude/agents/utils.py
rename to apps/backend/agents/utils.py
diff --git a/auto-claude/analysis/__init__.py b/apps/backend/analysis/__init__.py
similarity index 100%
rename from auto-claude/analysis/__init__.py
rename to apps/backend/analysis/__init__.py
diff --git a/auto-claude/analysis/analyzer.py b/apps/backend/analysis/analyzer.py
similarity index 100%
rename from auto-claude/analysis/analyzer.py
rename to apps/backend/analysis/analyzer.py
diff --git a/auto-claude/analysis/analyzers/__init__.py b/apps/backend/analysis/analyzers/__init__.py
similarity index 100%
rename from auto-claude/analysis/analyzers/__init__.py
rename to apps/backend/analysis/analyzers/__init__.py
diff --git a/auto-claude/analysis/analyzers/base.py b/apps/backend/analysis/analyzers/base.py
similarity index 100%
rename from auto-claude/analysis/analyzers/base.py
rename to apps/backend/analysis/analyzers/base.py
diff --git a/auto-claude/analysis/analyzers/context/__init__.py b/apps/backend/analysis/analyzers/context/__init__.py
similarity index 100%
rename from auto-claude/analysis/analyzers/context/__init__.py
rename to apps/backend/analysis/analyzers/context/__init__.py
diff --git a/auto-claude/analysis/analyzers/context/api_docs_detector.py b/apps/backend/analysis/analyzers/context/api_docs_detector.py
similarity index 100%
rename from auto-claude/analysis/analyzers/context/api_docs_detector.py
rename to apps/backend/analysis/analyzers/context/api_docs_detector.py
diff --git a/auto-claude/analysis/analyzers/context/auth_detector.py b/apps/backend/analysis/analyzers/context/auth_detector.py
similarity index 100%
rename from auto-claude/analysis/analyzers/context/auth_detector.py
rename to apps/backend/analysis/analyzers/context/auth_detector.py
diff --git a/auto-claude/analysis/analyzers/context/env_detector.py b/apps/backend/analysis/analyzers/context/env_detector.py
similarity index 100%
rename from auto-claude/analysis/analyzers/context/env_detector.py
rename to apps/backend/analysis/analyzers/context/env_detector.py
diff --git a/auto-claude/analysis/analyzers/context/jobs_detector.py b/apps/backend/analysis/analyzers/context/jobs_detector.py
similarity index 100%
rename from auto-claude/analysis/analyzers/context/jobs_detector.py
rename to apps/backend/analysis/analyzers/context/jobs_detector.py
diff --git a/auto-claude/analysis/analyzers/context/migrations_detector.py b/apps/backend/analysis/analyzers/context/migrations_detector.py
similarity index 100%
rename from auto-claude/analysis/analyzers/context/migrations_detector.py
rename to apps/backend/analysis/analyzers/context/migrations_detector.py
diff --git a/auto-claude/analysis/analyzers/context/monitoring_detector.py b/apps/backend/analysis/analyzers/context/monitoring_detector.py
similarity index 100%
rename from auto-claude/analysis/analyzers/context/monitoring_detector.py
rename to apps/backend/analysis/analyzers/context/monitoring_detector.py
diff --git a/auto-claude/analysis/analyzers/context/services_detector.py b/apps/backend/analysis/analyzers/context/services_detector.py
similarity index 100%
rename from auto-claude/analysis/analyzers/context/services_detector.py
rename to apps/backend/analysis/analyzers/context/services_detector.py
diff --git a/auto-claude/analysis/analyzers/context_analyzer.py b/apps/backend/analysis/analyzers/context_analyzer.py
similarity index 100%
rename from auto-claude/analysis/analyzers/context_analyzer.py
rename to apps/backend/analysis/analyzers/context_analyzer.py
diff --git a/auto-claude/analysis/analyzers/database_detector.py b/apps/backend/analysis/analyzers/database_detector.py
similarity index 100%
rename from auto-claude/analysis/analyzers/database_detector.py
rename to apps/backend/analysis/analyzers/database_detector.py
diff --git a/auto-claude/analysis/analyzers/framework_analyzer.py b/apps/backend/analysis/analyzers/framework_analyzer.py
similarity index 100%
rename from auto-claude/analysis/analyzers/framework_analyzer.py
rename to apps/backend/analysis/analyzers/framework_analyzer.py
diff --git a/auto-claude/analysis/analyzers/port_detector.py b/apps/backend/analysis/analyzers/port_detector.py
similarity index 100%
rename from auto-claude/analysis/analyzers/port_detector.py
rename to apps/backend/analysis/analyzers/port_detector.py
diff --git a/auto-claude/analysis/analyzers/project_analyzer_module.py b/apps/backend/analysis/analyzers/project_analyzer_module.py
similarity index 100%
rename from auto-claude/analysis/analyzers/project_analyzer_module.py
rename to apps/backend/analysis/analyzers/project_analyzer_module.py
diff --git a/auto-claude/analysis/analyzers/route_detector.py b/apps/backend/analysis/analyzers/route_detector.py
similarity index 100%
rename from auto-claude/analysis/analyzers/route_detector.py
rename to apps/backend/analysis/analyzers/route_detector.py
diff --git a/auto-claude/analysis/analyzers/service_analyzer.py b/apps/backend/analysis/analyzers/service_analyzer.py
similarity index 100%
rename from auto-claude/analysis/analyzers/service_analyzer.py
rename to apps/backend/analysis/analyzers/service_analyzer.py
diff --git a/auto-claude/analysis/ci_discovery.py b/apps/backend/analysis/ci_discovery.py
similarity index 100%
rename from auto-claude/analysis/ci_discovery.py
rename to apps/backend/analysis/ci_discovery.py
diff --git a/auto-claude/analysis/insight_extractor.py b/apps/backend/analysis/insight_extractor.py
similarity index 100%
rename from auto-claude/analysis/insight_extractor.py
rename to apps/backend/analysis/insight_extractor.py
diff --git a/auto-claude/analysis/project_analyzer.py b/apps/backend/analysis/project_analyzer.py
similarity index 100%
rename from auto-claude/analysis/project_analyzer.py
rename to apps/backend/analysis/project_analyzer.py
diff --git a/auto-claude/analysis/risk_classifier.py b/apps/backend/analysis/risk_classifier.py
similarity index 100%
rename from auto-claude/analysis/risk_classifier.py
rename to apps/backend/analysis/risk_classifier.py
diff --git a/auto-claude/analysis/security_scanner.py b/apps/backend/analysis/security_scanner.py
similarity index 100%
rename from auto-claude/analysis/security_scanner.py
rename to apps/backend/analysis/security_scanner.py
diff --git a/auto-claude/analysis/test_discovery.py b/apps/backend/analysis/test_discovery.py
similarity index 100%
rename from auto-claude/analysis/test_discovery.py
rename to apps/backend/analysis/test_discovery.py
diff --git a/apps/backend/analyzer.py b/apps/backend/analyzer.py
new file mode 100644
index 00000000..847eb400
--- /dev/null
+++ b/apps/backend/analyzer.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+"""
+Analyzer facade module.
+
+Provides backward compatibility for scripts that import from analyzer.py at the root.
+Actual implementation is in analysis/analyzer.py.
+"""
+
+from analysis.analyzer import (
+ ProjectAnalyzer,
+ ServiceAnalyzer,
+ analyze_project,
+ analyze_service,
+ main,
+)
+
+__all__ = [
+ "ServiceAnalyzer",
+ "ProjectAnalyzer",
+ "analyze_project",
+ "analyze_service",
+ "main",
+]
+
+if __name__ == "__main__":
+ main()
diff --git a/apps/backend/auto_claude_tools.py b/apps/backend/auto_claude_tools.py
new file mode 100644
index 00000000..d774c5cc
--- /dev/null
+++ b/apps/backend/auto_claude_tools.py
@@ -0,0 +1,36 @@
+"""
+Auto Claude tools module facade.
+
+Provides MCP tools for agent operations.
+Re-exports from agents.tools_pkg for clean imports.
+"""
+
+from agents.tools_pkg.models import ( # noqa: F401
+ ELECTRON_TOOLS,
+ TOOL_GET_BUILD_PROGRESS,
+ TOOL_GET_SESSION_CONTEXT,
+ TOOL_RECORD_DISCOVERY,
+ TOOL_RECORD_GOTCHA,
+ TOOL_UPDATE_QA_STATUS,
+ TOOL_UPDATE_SUBTASK_STATUS,
+ is_electron_mcp_enabled,
+)
+from agents.tools_pkg.permissions import get_allowed_tools # noqa: F401
+from agents.tools_pkg.registry import ( # noqa: F401
+ create_auto_claude_mcp_server,
+ is_tools_available,
+)
+
+__all__ = [
+ "create_auto_claude_mcp_server",
+ "get_allowed_tools",
+ "is_tools_available",
+ "TOOL_UPDATE_SUBTASK_STATUS",
+ "TOOL_GET_BUILD_PROGRESS",
+ "TOOL_RECORD_DISCOVERY",
+ "TOOL_RECORD_GOTCHA",
+ "TOOL_GET_SESSION_CONTEXT",
+ "TOOL_UPDATE_QA_STATUS",
+ "ELECTRON_TOOLS",
+ "is_electron_mcp_enabled",
+]
diff --git a/auto-claude/ci_discovery.py b/apps/backend/ci_discovery.py
similarity index 100%
rename from auto-claude/ci_discovery.py
rename to apps/backend/ci_discovery.py
diff --git a/auto-claude/cli/__init__.py b/apps/backend/cli/__init__.py
similarity index 100%
rename from auto-claude/cli/__init__.py
rename to apps/backend/cli/__init__.py
diff --git a/auto-claude/cli/build_commands.py b/apps/backend/cli/build_commands.py
similarity index 100%
rename from auto-claude/cli/build_commands.py
rename to apps/backend/cli/build_commands.py
diff --git a/auto-claude/cli/followup_commands.py b/apps/backend/cli/followup_commands.py
similarity index 100%
rename from auto-claude/cli/followup_commands.py
rename to apps/backend/cli/followup_commands.py
diff --git a/auto-claude/cli/input_handlers.py b/apps/backend/cli/input_handlers.py
similarity index 100%
rename from auto-claude/cli/input_handlers.py
rename to apps/backend/cli/input_handlers.py
diff --git a/auto-claude/cli/main.py b/apps/backend/cli/main.py
similarity index 100%
rename from auto-claude/cli/main.py
rename to apps/backend/cli/main.py
diff --git a/auto-claude/cli/qa_commands.py b/apps/backend/cli/qa_commands.py
similarity index 100%
rename from auto-claude/cli/qa_commands.py
rename to apps/backend/cli/qa_commands.py
diff --git a/auto-claude/cli/spec_commands.py b/apps/backend/cli/spec_commands.py
similarity index 58%
rename from auto-claude/cli/spec_commands.py
rename to apps/backend/cli/spec_commands.py
index c20c0914..2fa1d02c 100644
--- a/auto-claude/cli/spec_commands.py
+++ b/apps/backend/cli/spec_commands.py
@@ -93,14 +93,76 @@ def list_specs(project_dir: Path, dev_mode: bool = False) -> list[dict]:
return specs
-def print_specs_list(project_dir: Path, dev_mode: bool = False) -> None:
- """Print a formatted list of all specs."""
+def print_specs_list(
+ project_dir: Path, dev_mode: bool = False, auto_create: bool = True
+) -> None:
+ """Print a formatted list of all specs.
+
+ Args:
+ project_dir: Project root directory
+ dev_mode: If True, use dev/auto-claude/specs/
+ auto_create: If True and no specs exist, automatically launch spec creation
+ """
+ import subprocess
+
specs = list_specs(project_dir, dev_mode)
if not specs:
print("\nNo specs found.")
- print("\nCreate your first spec:")
- print(" claude /spec")
+
+ if auto_create:
+ # Get the backend directory and find spec_runner.py
+ backend_dir = Path(__file__).parent.parent
+ spec_runner = backend_dir / "runners" / "spec_runner.py"
+
+ # Find Python executable - use current interpreter
+ python_path = sys.executable
+
+ if spec_runner.exists() and python_path:
+ # Quick prompt for task description
+ print("\n" + "=" * 60)
+ print(" QUICK START")
+ print("=" * 60)
+ print("\nWhat do you want to build?")
+ print(
+ "(Enter a brief description, or press Enter for interactive mode)\n"
+ )
+
+ try:
+ task = input("> ").strip()
+ except (EOFError, KeyboardInterrupt):
+ print("\nCancelled.")
+ return
+
+ if task:
+ # Direct mode: create spec and start building
+ print(f"\nStarting build for: {task}\n")
+ subprocess.run(
+ [
+ python_path,
+ str(spec_runner),
+ "--task",
+ task,
+ "--complexity",
+ "simple",
+ "--auto-approve",
+ ],
+ cwd=project_dir,
+ )
+ else:
+ # Interactive mode
+ print("\nLaunching interactive mode...\n")
+ subprocess.run(
+ [python_path, str(spec_runner), "--interactive"],
+ cwd=project_dir,
+ )
+ return
+ else:
+ print("\nCreate your first spec:")
+ print(" python runners/spec_runner.py --interactive")
+ else:
+ print("\nCreate your first spec:")
+ print(" python runners/spec_runner.py --interactive")
return
print("\n" + "=" * 70)
diff --git a/auto-claude/cli/utils.py b/apps/backend/cli/utils.py
similarity index 100%
rename from auto-claude/cli/utils.py
rename to apps/backend/cli/utils.py
diff --git a/auto-claude/cli/workspace_commands.py b/apps/backend/cli/workspace_commands.py
similarity index 100%
rename from auto-claude/cli/workspace_commands.py
rename to apps/backend/cli/workspace_commands.py
diff --git a/apps/backend/client.py b/apps/backend/client.py
new file mode 100644
index 00000000..4b144f97
--- /dev/null
+++ b/apps/backend/client.py
@@ -0,0 +1,25 @@
+"""
+Claude client module facade.
+
+Provides Claude API client utilities.
+Uses lazy imports to avoid circular dependencies.
+"""
+
+
+def __getattr__(name):
+ """Lazy import to avoid circular imports with auto_claude_tools."""
+ from core import client as _client
+
+ return getattr(_client, name)
+
+
+def create_client(*args, **kwargs):
+ """Create a Claude client instance."""
+ from core.client import create_client as _create_client
+
+ return _create_client(*args, **kwargs)
+
+
+__all__ = [
+ "create_client",
+]
diff --git a/auto-claude/commit_message.py b/apps/backend/commit_message.py
similarity index 100%
rename from auto-claude/commit_message.py
rename to apps/backend/commit_message.py
diff --git a/auto-claude/context/__init__.py b/apps/backend/context/__init__.py
similarity index 100%
rename from auto-claude/context/__init__.py
rename to apps/backend/context/__init__.py
diff --git a/auto-claude/context/builder.py b/apps/backend/context/builder.py
similarity index 100%
rename from auto-claude/context/builder.py
rename to apps/backend/context/builder.py
diff --git a/auto-claude/context/categorizer.py b/apps/backend/context/categorizer.py
similarity index 100%
rename from auto-claude/context/categorizer.py
rename to apps/backend/context/categorizer.py
diff --git a/auto-claude/context/constants.py b/apps/backend/context/constants.py
similarity index 100%
rename from auto-claude/context/constants.py
rename to apps/backend/context/constants.py
diff --git a/auto-claude/context/graphiti_integration.py b/apps/backend/context/graphiti_integration.py
similarity index 100%
rename from auto-claude/context/graphiti_integration.py
rename to apps/backend/context/graphiti_integration.py
diff --git a/auto-claude/context/keyword_extractor.py b/apps/backend/context/keyword_extractor.py
similarity index 100%
rename from auto-claude/context/keyword_extractor.py
rename to apps/backend/context/keyword_extractor.py
diff --git a/auto-claude/context/main.py b/apps/backend/context/main.py
similarity index 100%
rename from auto-claude/context/main.py
rename to apps/backend/context/main.py
diff --git a/auto-claude/context/models.py b/apps/backend/context/models.py
similarity index 100%
rename from auto-claude/context/models.py
rename to apps/backend/context/models.py
diff --git a/auto-claude/context/pattern_discovery.py b/apps/backend/context/pattern_discovery.py
similarity index 100%
rename from auto-claude/context/pattern_discovery.py
rename to apps/backend/context/pattern_discovery.py
diff --git a/auto-claude/context/search.py b/apps/backend/context/search.py
similarity index 100%
rename from auto-claude/context/search.py
rename to apps/backend/context/search.py
diff --git a/auto-claude/context/serialization.py b/apps/backend/context/serialization.py
similarity index 100%
rename from auto-claude/context/serialization.py
rename to apps/backend/context/serialization.py
diff --git a/auto-claude/context/service_matcher.py b/apps/backend/context/service_matcher.py
similarity index 100%
rename from auto-claude/context/service_matcher.py
rename to apps/backend/context/service_matcher.py
diff --git a/auto-claude/core/__init__.py b/apps/backend/core/__init__.py
similarity index 100%
rename from auto-claude/core/__init__.py
rename to apps/backend/core/__init__.py
diff --git a/auto-claude/core/agent.py b/apps/backend/core/agent.py
similarity index 100%
rename from auto-claude/core/agent.py
rename to apps/backend/core/agent.py
diff --git a/auto-claude/core/auth.py b/apps/backend/core/auth.py
similarity index 100%
rename from auto-claude/core/auth.py
rename to apps/backend/core/auth.py
diff --git a/auto-claude/core/client.py b/apps/backend/core/client.py
similarity index 98%
rename from auto-claude/core/client.py
rename to apps/backend/core/client.py
index a1d6ec64..48de8d87 100644
--- a/auto-claude/core/client.py
+++ b/apps/backend/core/client.py
@@ -96,7 +96,7 @@ CONTEXT7_TOOLS = [
]
# Graphiti MCP tools for knowledge graph memory (when GRAPHITI_MCP_ENABLED is set)
-# See: https://docs.falkordb.com/agentic-memory/graphiti-mcp-server.html
+# See: https://github.com/getzep/graphiti
GRAPHITI_MCP_TOOLS = [
"mcp__graphiti-memory__search_nodes", # Search entity summaries
"mcp__graphiti-memory__search_facts", # Search relationships between entities
@@ -321,7 +321,7 @@ def create_client(
}
# Add Graphiti MCP server if enabled
- # Requires running: docker run -d -p 8000:8000 falkordb/graphiti-knowledge-graph-mcp
+ # Graphiti MCP server for knowledge graph memory (uses embedded LadybugDB)
if graphiti_mcp_enabled:
mcp_servers["graphiti-memory"] = {
"type": "http",
diff --git a/auto-claude/core/debug.py b/apps/backend/core/debug.py
similarity index 100%
rename from auto-claude/core/debug.py
rename to apps/backend/core/debug.py
diff --git a/auto-claude/core/progress.py b/apps/backend/core/progress.py
similarity index 100%
rename from auto-claude/core/progress.py
rename to apps/backend/core/progress.py
diff --git a/auto-claude/core/workspace.py b/apps/backend/core/workspace.py
similarity index 100%
rename from auto-claude/core/workspace.py
rename to apps/backend/core/workspace.py
diff --git a/auto-claude/core/workspace/README.md b/apps/backend/core/workspace/README.md
similarity index 100%
rename from auto-claude/core/workspace/README.md
rename to apps/backend/core/workspace/README.md
diff --git a/auto-claude/core/workspace/__init__.py b/apps/backend/core/workspace/__init__.py
similarity index 100%
rename from auto-claude/core/workspace/__init__.py
rename to apps/backend/core/workspace/__init__.py
diff --git a/auto-claude/core/workspace/display.py b/apps/backend/core/workspace/display.py
similarity index 100%
rename from auto-claude/core/workspace/display.py
rename to apps/backend/core/workspace/display.py
diff --git a/auto-claude/core/workspace/finalization.py b/apps/backend/core/workspace/finalization.py
similarity index 100%
rename from auto-claude/core/workspace/finalization.py
rename to apps/backend/core/workspace/finalization.py
diff --git a/auto-claude/core/workspace/git_utils.py b/apps/backend/core/workspace/git_utils.py
similarity index 100%
rename from auto-claude/core/workspace/git_utils.py
rename to apps/backend/core/workspace/git_utils.py
diff --git a/auto-claude/core/workspace/models.py b/apps/backend/core/workspace/models.py
similarity index 100%
rename from auto-claude/core/workspace/models.py
rename to apps/backend/core/workspace/models.py
diff --git a/auto-claude/core/workspace/setup.py b/apps/backend/core/workspace/setup.py
similarity index 100%
rename from auto-claude/core/workspace/setup.py
rename to apps/backend/core/workspace/setup.py
diff --git a/auto-claude/core/worktree.py b/apps/backend/core/worktree.py
similarity index 100%
rename from auto-claude/core/worktree.py
rename to apps/backend/core/worktree.py
diff --git a/auto-claude/critique.py b/apps/backend/critique.py
similarity index 100%
rename from auto-claude/critique.py
rename to apps/backend/critique.py
diff --git a/apps/backend/debug.py b/apps/backend/debug.py
new file mode 100644
index 00000000..14aae6f1
--- /dev/null
+++ b/apps/backend/debug.py
@@ -0,0 +1,40 @@
+"""
+Debug module facade.
+
+Provides debug logging utilities for the Auto-Claude framework.
+Re-exports from core.debug for clean imports.
+"""
+
+from core.debug import (
+ Colors,
+ debug,
+ debug_async_timer,
+ debug_detailed,
+ debug_env_status,
+ debug_error,
+ debug_info,
+ debug_section,
+ debug_success,
+ debug_timer,
+ debug_verbose,
+ debug_warning,
+ get_debug_level,
+ is_debug_enabled,
+)
+
+__all__ = [
+ "Colors",
+ "debug",
+ "debug_async_timer",
+ "debug_detailed",
+ "debug_env_status",
+ "debug_error",
+ "debug_info",
+ "debug_section",
+ "debug_success",
+ "debug_timer",
+ "debug_verbose",
+ "debug_warning",
+ "get_debug_level",
+ "is_debug_enabled",
+]
diff --git a/auto-claude/graphiti_config.py b/apps/backend/graphiti_config.py
similarity index 100%
rename from auto-claude/graphiti_config.py
rename to apps/backend/graphiti_config.py
diff --git a/auto-claude/graphiti_providers.py b/apps/backend/graphiti_providers.py
similarity index 100%
rename from auto-claude/graphiti_providers.py
rename to apps/backend/graphiti_providers.py
diff --git a/auto-claude/ideation/__init__.py b/apps/backend/ideation/__init__.py
similarity index 100%
rename from auto-claude/ideation/__init__.py
rename to apps/backend/ideation/__init__.py
diff --git a/auto-claude/ideation/analyzer.py b/apps/backend/ideation/analyzer.py
similarity index 100%
rename from auto-claude/ideation/analyzer.py
rename to apps/backend/ideation/analyzer.py
diff --git a/auto-claude/ideation/config.py b/apps/backend/ideation/config.py
similarity index 100%
rename from auto-claude/ideation/config.py
rename to apps/backend/ideation/config.py
diff --git a/auto-claude/ideation/formatter.py b/apps/backend/ideation/formatter.py
similarity index 100%
rename from auto-claude/ideation/formatter.py
rename to apps/backend/ideation/formatter.py
diff --git a/auto-claude/ideation/generator.py b/apps/backend/ideation/generator.py
similarity index 100%
rename from auto-claude/ideation/generator.py
rename to apps/backend/ideation/generator.py
diff --git a/auto-claude/ideation/output_streamer.py b/apps/backend/ideation/output_streamer.py
similarity index 100%
rename from auto-claude/ideation/output_streamer.py
rename to apps/backend/ideation/output_streamer.py
diff --git a/auto-claude/ideation/phase_executor.py b/apps/backend/ideation/phase_executor.py
similarity index 100%
rename from auto-claude/ideation/phase_executor.py
rename to apps/backend/ideation/phase_executor.py
diff --git a/auto-claude/ideation/prioritizer.py b/apps/backend/ideation/prioritizer.py
similarity index 100%
rename from auto-claude/ideation/prioritizer.py
rename to apps/backend/ideation/prioritizer.py
diff --git a/auto-claude/ideation/project_index_phase.py b/apps/backend/ideation/project_index_phase.py
similarity index 100%
rename from auto-claude/ideation/project_index_phase.py
rename to apps/backend/ideation/project_index_phase.py
diff --git a/auto-claude/ideation/runner.py b/apps/backend/ideation/runner.py
similarity index 100%
rename from auto-claude/ideation/runner.py
rename to apps/backend/ideation/runner.py
diff --git a/auto-claude/ideation/script_runner.py b/apps/backend/ideation/script_runner.py
similarity index 100%
rename from auto-claude/ideation/script_runner.py
rename to apps/backend/ideation/script_runner.py
diff --git a/auto-claude/ideation/types.py b/apps/backend/ideation/types.py
similarity index 100%
rename from auto-claude/ideation/types.py
rename to apps/backend/ideation/types.py
diff --git a/auto-claude/implementation_plan/__init__.py b/apps/backend/implementation_plan/__init__.py
similarity index 100%
rename from auto-claude/implementation_plan/__init__.py
rename to apps/backend/implementation_plan/__init__.py
diff --git a/auto-claude/implementation_plan/enums.py b/apps/backend/implementation_plan/enums.py
similarity index 100%
rename from auto-claude/implementation_plan/enums.py
rename to apps/backend/implementation_plan/enums.py
diff --git a/auto-claude/implementation_plan/factories.py b/apps/backend/implementation_plan/factories.py
similarity index 100%
rename from auto-claude/implementation_plan/factories.py
rename to apps/backend/implementation_plan/factories.py
diff --git a/auto-claude/implementation_plan/main.py b/apps/backend/implementation_plan/main.py
similarity index 100%
rename from auto-claude/implementation_plan/main.py
rename to apps/backend/implementation_plan/main.py
diff --git a/auto-claude/implementation_plan/phase.py b/apps/backend/implementation_plan/phase.py
similarity index 100%
rename from auto-claude/implementation_plan/phase.py
rename to apps/backend/implementation_plan/phase.py
diff --git a/auto-claude/implementation_plan/plan.py b/apps/backend/implementation_plan/plan.py
similarity index 100%
rename from auto-claude/implementation_plan/plan.py
rename to apps/backend/implementation_plan/plan.py
diff --git a/auto-claude/implementation_plan/subtask.py b/apps/backend/implementation_plan/subtask.py
similarity index 100%
rename from auto-claude/implementation_plan/subtask.py
rename to apps/backend/implementation_plan/subtask.py
diff --git a/auto-claude/implementation_plan/verification.py b/apps/backend/implementation_plan/verification.py
similarity index 100%
rename from auto-claude/implementation_plan/verification.py
rename to apps/backend/implementation_plan/verification.py
diff --git a/auto-claude/init.py b/apps/backend/init.py
similarity index 100%
rename from auto-claude/init.py
rename to apps/backend/init.py
diff --git a/auto-claude/insight_extractor.py b/apps/backend/insight_extractor.py
similarity index 100%
rename from auto-claude/insight_extractor.py
rename to apps/backend/insight_extractor.py
diff --git a/auto-claude/integrations/__init__.py b/apps/backend/integrations/__init__.py
similarity index 100%
rename from auto-claude/integrations/__init__.py
rename to apps/backend/integrations/__init__.py
diff --git a/auto-claude/integrations/graphiti/__init__.py b/apps/backend/integrations/graphiti/__init__.py
similarity index 100%
rename from auto-claude/integrations/graphiti/__init__.py
rename to apps/backend/integrations/graphiti/__init__.py
diff --git a/auto-claude/integrations/graphiti/config.py b/apps/backend/integrations/graphiti/config.py
similarity index 100%
rename from auto-claude/integrations/graphiti/config.py
rename to apps/backend/integrations/graphiti/config.py
diff --git a/auto-claude/integrations/graphiti/memory.py b/apps/backend/integrations/graphiti/memory.py
similarity index 96%
rename from auto-claude/integrations/graphiti/memory.py
rename to apps/backend/integrations/graphiti/memory.py
index 9739f34c..7b160c81 100644
--- a/auto-claude/integrations/graphiti/memory.py
+++ b/apps/backend/integrations/graphiti/memory.py
@@ -7,7 +7,7 @@ memory system from the auto-claude/graphiti/ package.
The refactored code is now organized as:
- graphiti/graphiti.py - Main GraphitiMemory class
-- graphiti/client.py - FalkorDB client wrapper
+- graphiti/client.py - LadybugDB client wrapper
- graphiti/queries.py - Graph query operations
- graphiti/search.py - Semantic search logic
- graphiti/schema.py - Graph schema definitions
@@ -70,7 +70,7 @@ def get_graphiti_memory(
async def test_graphiti_connection() -> tuple[bool, str]:
"""
- Test if FalkorDB is available and Graphiti can connect.
+ Test if LadybugDB is available and Graphiti can connect.
Returns:
Tuple of (success: bool, message: str)
@@ -116,7 +116,7 @@ async def test_graphiti_connection() -> tuple[bool, str]:
await graphiti.close()
return True, (
- f"Connected to FalkorDB at {config.falkordb_host}:{config.falkordb_port} "
+ f"Connected to LadybugDB at {config.falkordb_host}:{config.falkordb_port} "
f"(providers: {config.get_provider_summary()})"
)
diff --git a/auto-claude/integrations/graphiti/migrate_embeddings.py b/apps/backend/integrations/graphiti/migrate_embeddings.py
similarity index 100%
rename from auto-claude/integrations/graphiti/migrate_embeddings.py
rename to apps/backend/integrations/graphiti/migrate_embeddings.py
diff --git a/auto-claude/integrations/graphiti/providers.py b/apps/backend/integrations/graphiti/providers.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers.py
rename to apps/backend/integrations/graphiti/providers.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/__init__.py b/apps/backend/integrations/graphiti/providers_pkg/__init__.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/__init__.py
rename to apps/backend/integrations/graphiti/providers_pkg/__init__.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/cross_encoder.py b/apps/backend/integrations/graphiti/providers_pkg/cross_encoder.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/cross_encoder.py
rename to apps/backend/integrations/graphiti/providers_pkg/cross_encoder.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/embedder_providers/__init__.py b/apps/backend/integrations/graphiti/providers_pkg/embedder_providers/__init__.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/embedder_providers/__init__.py
rename to apps/backend/integrations/graphiti/providers_pkg/embedder_providers/__init__.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/embedder_providers/azure_openai_embedder.py b/apps/backend/integrations/graphiti/providers_pkg/embedder_providers/azure_openai_embedder.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/embedder_providers/azure_openai_embedder.py
rename to apps/backend/integrations/graphiti/providers_pkg/embedder_providers/azure_openai_embedder.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/embedder_providers/google_embedder.py b/apps/backend/integrations/graphiti/providers_pkg/embedder_providers/google_embedder.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/embedder_providers/google_embedder.py
rename to apps/backend/integrations/graphiti/providers_pkg/embedder_providers/google_embedder.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/embedder_providers/ollama_embedder.py b/apps/backend/integrations/graphiti/providers_pkg/embedder_providers/ollama_embedder.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/embedder_providers/ollama_embedder.py
rename to apps/backend/integrations/graphiti/providers_pkg/embedder_providers/ollama_embedder.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/embedder_providers/openai_embedder.py b/apps/backend/integrations/graphiti/providers_pkg/embedder_providers/openai_embedder.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/embedder_providers/openai_embedder.py
rename to apps/backend/integrations/graphiti/providers_pkg/embedder_providers/openai_embedder.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/embedder_providers/voyage_embedder.py b/apps/backend/integrations/graphiti/providers_pkg/embedder_providers/voyage_embedder.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/embedder_providers/voyage_embedder.py
rename to apps/backend/integrations/graphiti/providers_pkg/embedder_providers/voyage_embedder.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/exceptions.py b/apps/backend/integrations/graphiti/providers_pkg/exceptions.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/exceptions.py
rename to apps/backend/integrations/graphiti/providers_pkg/exceptions.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/factory.py b/apps/backend/integrations/graphiti/providers_pkg/factory.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/factory.py
rename to apps/backend/integrations/graphiti/providers_pkg/factory.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/llm_providers/__init__.py b/apps/backend/integrations/graphiti/providers_pkg/llm_providers/__init__.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/llm_providers/__init__.py
rename to apps/backend/integrations/graphiti/providers_pkg/llm_providers/__init__.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/llm_providers/anthropic_llm.py b/apps/backend/integrations/graphiti/providers_pkg/llm_providers/anthropic_llm.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/llm_providers/anthropic_llm.py
rename to apps/backend/integrations/graphiti/providers_pkg/llm_providers/anthropic_llm.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/llm_providers/azure_openai_llm.py b/apps/backend/integrations/graphiti/providers_pkg/llm_providers/azure_openai_llm.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/llm_providers/azure_openai_llm.py
rename to apps/backend/integrations/graphiti/providers_pkg/llm_providers/azure_openai_llm.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/llm_providers/google_llm.py b/apps/backend/integrations/graphiti/providers_pkg/llm_providers/google_llm.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/llm_providers/google_llm.py
rename to apps/backend/integrations/graphiti/providers_pkg/llm_providers/google_llm.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/llm_providers/ollama_llm.py b/apps/backend/integrations/graphiti/providers_pkg/llm_providers/ollama_llm.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/llm_providers/ollama_llm.py
rename to apps/backend/integrations/graphiti/providers_pkg/llm_providers/ollama_llm.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/llm_providers/openai_llm.py b/apps/backend/integrations/graphiti/providers_pkg/llm_providers/openai_llm.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/llm_providers/openai_llm.py
rename to apps/backend/integrations/graphiti/providers_pkg/llm_providers/openai_llm.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/models.py b/apps/backend/integrations/graphiti/providers_pkg/models.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/models.py
rename to apps/backend/integrations/graphiti/providers_pkg/models.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/utils.py b/apps/backend/integrations/graphiti/providers_pkg/utils.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/utils.py
rename to apps/backend/integrations/graphiti/providers_pkg/utils.py
diff --git a/auto-claude/integrations/graphiti/providers_pkg/validators.py b/apps/backend/integrations/graphiti/providers_pkg/validators.py
similarity index 100%
rename from auto-claude/integrations/graphiti/providers_pkg/validators.py
rename to apps/backend/integrations/graphiti/providers_pkg/validators.py
diff --git a/auto-claude/integrations/graphiti/queries_pkg/__init__.py b/apps/backend/integrations/graphiti/queries_pkg/__init__.py
similarity index 100%
rename from auto-claude/integrations/graphiti/queries_pkg/__init__.py
rename to apps/backend/integrations/graphiti/queries_pkg/__init__.py
diff --git a/auto-claude/integrations/graphiti/queries_pkg/client.py b/apps/backend/integrations/graphiti/queries_pkg/client.py
similarity index 100%
rename from auto-claude/integrations/graphiti/queries_pkg/client.py
rename to apps/backend/integrations/graphiti/queries_pkg/client.py
diff --git a/auto-claude/integrations/graphiti/queries_pkg/graphiti.py b/apps/backend/integrations/graphiti/queries_pkg/graphiti.py
similarity index 100%
rename from auto-claude/integrations/graphiti/queries_pkg/graphiti.py
rename to apps/backend/integrations/graphiti/queries_pkg/graphiti.py
diff --git a/auto-claude/integrations/graphiti/queries_pkg/kuzu_driver_patched.py b/apps/backend/integrations/graphiti/queries_pkg/kuzu_driver_patched.py
similarity index 100%
rename from auto-claude/integrations/graphiti/queries_pkg/kuzu_driver_patched.py
rename to apps/backend/integrations/graphiti/queries_pkg/kuzu_driver_patched.py
diff --git a/auto-claude/integrations/graphiti/queries_pkg/queries.py b/apps/backend/integrations/graphiti/queries_pkg/queries.py
similarity index 100%
rename from auto-claude/integrations/graphiti/queries_pkg/queries.py
rename to apps/backend/integrations/graphiti/queries_pkg/queries.py
diff --git a/auto-claude/integrations/graphiti/queries_pkg/schema.py b/apps/backend/integrations/graphiti/queries_pkg/schema.py
similarity index 100%
rename from auto-claude/integrations/graphiti/queries_pkg/schema.py
rename to apps/backend/integrations/graphiti/queries_pkg/schema.py
diff --git a/auto-claude/integrations/graphiti/queries_pkg/search.py b/apps/backend/integrations/graphiti/queries_pkg/search.py
similarity index 100%
rename from auto-claude/integrations/graphiti/queries_pkg/search.py
rename to apps/backend/integrations/graphiti/queries_pkg/search.py
diff --git a/auto-claude/integrations/graphiti/test_graphiti_memory.py b/apps/backend/integrations/graphiti/test_graphiti_memory.py
similarity index 100%
rename from auto-claude/integrations/graphiti/test_graphiti_memory.py
rename to apps/backend/integrations/graphiti/test_graphiti_memory.py
diff --git a/auto-claude/integrations/graphiti/test_provider_naming.py b/apps/backend/integrations/graphiti/test_provider_naming.py
similarity index 100%
rename from auto-claude/integrations/graphiti/test_provider_naming.py
rename to apps/backend/integrations/graphiti/test_provider_naming.py
diff --git a/auto-claude/integrations/linear/__init__.py b/apps/backend/integrations/linear/__init__.py
similarity index 100%
rename from auto-claude/integrations/linear/__init__.py
rename to apps/backend/integrations/linear/__init__.py
diff --git a/auto-claude/integrations/linear/config.py b/apps/backend/integrations/linear/config.py
similarity index 100%
rename from auto-claude/integrations/linear/config.py
rename to apps/backend/integrations/linear/config.py
diff --git a/auto-claude/integrations/linear/integration.py b/apps/backend/integrations/linear/integration.py
similarity index 100%
rename from auto-claude/integrations/linear/integration.py
rename to apps/backend/integrations/linear/integration.py
diff --git a/auto-claude/integrations/linear/updater.py b/apps/backend/integrations/linear/updater.py
similarity index 100%
rename from auto-claude/integrations/linear/updater.py
rename to apps/backend/integrations/linear/updater.py
diff --git a/auto-claude/linear_config.py b/apps/backend/linear_config.py
similarity index 100%
rename from auto-claude/linear_config.py
rename to apps/backend/linear_config.py
diff --git a/apps/backend/linear_integration.py b/apps/backend/linear_integration.py
new file mode 100644
index 00000000..5eff31ee
--- /dev/null
+++ b/apps/backend/linear_integration.py
@@ -0,0 +1,22 @@
+"""
+Linear integration module facade.
+
+Provides Linear project management integration.
+Re-exports from integrations.linear.integration for clean imports.
+"""
+
+from integrations.linear.integration import (
+ LinearManager,
+ get_linear_manager,
+ is_linear_enabled,
+ prepare_coder_linear_instructions,
+ prepare_planner_linear_instructions,
+)
+
+__all__ = [
+ "LinearManager",
+ "get_linear_manager",
+ "is_linear_enabled",
+ "prepare_coder_linear_instructions",
+ "prepare_planner_linear_instructions",
+]
diff --git a/apps/backend/linear_updater.py b/apps/backend/linear_updater.py
new file mode 100644
index 00000000..9496385e
--- /dev/null
+++ b/apps/backend/linear_updater.py
@@ -0,0 +1,42 @@
+"""
+Linear updater module facade.
+
+Provides Linear integration functionality.
+Re-exports from integrations.linear.updater for clean imports.
+"""
+
+from integrations.linear.updater import (
+ LinearTaskState,
+ add_linear_comment,
+ create_linear_task,
+ get_linear_api_key,
+ is_linear_enabled,
+ linear_build_complete,
+ linear_qa_approved,
+ linear_qa_max_iterations,
+ linear_qa_rejected,
+ linear_qa_started,
+ linear_subtask_completed,
+ linear_subtask_failed,
+ linear_task_started,
+ linear_task_stuck,
+ update_linear_status,
+)
+
+__all__ = [
+ "LinearTaskState",
+ "add_linear_comment",
+ "create_linear_task",
+ "get_linear_api_key",
+ "is_linear_enabled",
+ "linear_build_complete",
+ "linear_qa_approved",
+ "linear_qa_max_iterations",
+ "linear_qa_rejected",
+ "linear_qa_started",
+ "linear_subtask_completed",
+ "linear_subtask_failed",
+ "linear_task_started",
+ "linear_task_stuck",
+ "update_linear_status",
+]
diff --git a/auto-claude/memory/__init__.py b/apps/backend/memory/__init__.py
similarity index 97%
rename from auto-claude/memory/__init__.py
rename to apps/backend/memory/__init__.py
index ea7b152c..76ecd672 100644
--- a/auto-claude/memory/__init__.py
+++ b/apps/backend/memory/__init__.py
@@ -10,7 +10,7 @@ Architecture Decision:
Memory System Hierarchy:
PRIMARY: Graphiti (when GRAPHITI_ENABLED=true)
- - Graph-based knowledge storage with FalkorDB
+ - Graph-based knowledge storage with LadybugDB (embedded Kuzu database)
- Semantic search across sessions
- Cross-project context retrieval
- Rich relationship modeling
diff --git a/auto-claude/memory/codebase_map.py b/apps/backend/memory/codebase_map.py
similarity index 100%
rename from auto-claude/memory/codebase_map.py
rename to apps/backend/memory/codebase_map.py
diff --git a/auto-claude/memory/graphiti_helpers.py b/apps/backend/memory/graphiti_helpers.py
similarity index 100%
rename from auto-claude/memory/graphiti_helpers.py
rename to apps/backend/memory/graphiti_helpers.py
diff --git a/auto-claude/memory/main.py b/apps/backend/memory/main.py
old mode 100755
new mode 100644
similarity index 100%
rename from auto-claude/memory/main.py
rename to apps/backend/memory/main.py
diff --git a/auto-claude/memory/paths.py b/apps/backend/memory/paths.py
similarity index 100%
rename from auto-claude/memory/paths.py
rename to apps/backend/memory/paths.py
diff --git a/auto-claude/memory/patterns.py b/apps/backend/memory/patterns.py
similarity index 100%
rename from auto-claude/memory/patterns.py
rename to apps/backend/memory/patterns.py
diff --git a/auto-claude/memory/sessions.py b/apps/backend/memory/sessions.py
similarity index 100%
rename from auto-claude/memory/sessions.py
rename to apps/backend/memory/sessions.py
diff --git a/auto-claude/memory/summary.py b/apps/backend/memory/summary.py
similarity index 100%
rename from auto-claude/memory/summary.py
rename to apps/backend/memory/summary.py
diff --git a/auto-claude/merge/__init__.py b/apps/backend/merge/__init__.py
similarity index 100%
rename from auto-claude/merge/__init__.py
rename to apps/backend/merge/__init__.py
diff --git a/auto-claude/merge/ai_resolver.py b/apps/backend/merge/ai_resolver.py
similarity index 100%
rename from auto-claude/merge/ai_resolver.py
rename to apps/backend/merge/ai_resolver.py
diff --git a/auto-claude/merge/ai_resolver/README.md b/apps/backend/merge/ai_resolver/README.md
similarity index 100%
rename from auto-claude/merge/ai_resolver/README.md
rename to apps/backend/merge/ai_resolver/README.md
diff --git a/auto-claude/merge/ai_resolver/__init__.py b/apps/backend/merge/ai_resolver/__init__.py
similarity index 100%
rename from auto-claude/merge/ai_resolver/__init__.py
rename to apps/backend/merge/ai_resolver/__init__.py
diff --git a/auto-claude/merge/ai_resolver/claude_client.py b/apps/backend/merge/ai_resolver/claude_client.py
similarity index 100%
rename from auto-claude/merge/ai_resolver/claude_client.py
rename to apps/backend/merge/ai_resolver/claude_client.py
diff --git a/auto-claude/merge/ai_resolver/context.py b/apps/backend/merge/ai_resolver/context.py
similarity index 100%
rename from auto-claude/merge/ai_resolver/context.py
rename to apps/backend/merge/ai_resolver/context.py
diff --git a/auto-claude/merge/ai_resolver/language_utils.py b/apps/backend/merge/ai_resolver/language_utils.py
similarity index 100%
rename from auto-claude/merge/ai_resolver/language_utils.py
rename to apps/backend/merge/ai_resolver/language_utils.py
diff --git a/auto-claude/merge/ai_resolver/parsers.py b/apps/backend/merge/ai_resolver/parsers.py
similarity index 100%
rename from auto-claude/merge/ai_resolver/parsers.py
rename to apps/backend/merge/ai_resolver/parsers.py
diff --git a/auto-claude/merge/ai_resolver/prompts.py b/apps/backend/merge/ai_resolver/prompts.py
similarity index 100%
rename from auto-claude/merge/ai_resolver/prompts.py
rename to apps/backend/merge/ai_resolver/prompts.py
diff --git a/auto-claude/merge/ai_resolver/resolver.py b/apps/backend/merge/ai_resolver/resolver.py
similarity index 100%
rename from auto-claude/merge/ai_resolver/resolver.py
rename to apps/backend/merge/ai_resolver/resolver.py
diff --git a/auto-claude/merge/auto_merger.py b/apps/backend/merge/auto_merger.py
similarity index 100%
rename from auto-claude/merge/auto_merger.py
rename to apps/backend/merge/auto_merger.py
diff --git a/auto-claude/merge/auto_merger/__init__.py b/apps/backend/merge/auto_merger/__init__.py
similarity index 100%
rename from auto-claude/merge/auto_merger/__init__.py
rename to apps/backend/merge/auto_merger/__init__.py
diff --git a/auto-claude/merge/auto_merger/context.py b/apps/backend/merge/auto_merger/context.py
similarity index 100%
rename from auto-claude/merge/auto_merger/context.py
rename to apps/backend/merge/auto_merger/context.py
diff --git a/auto-claude/merge/auto_merger/helpers.py b/apps/backend/merge/auto_merger/helpers.py
similarity index 100%
rename from auto-claude/merge/auto_merger/helpers.py
rename to apps/backend/merge/auto_merger/helpers.py
diff --git a/auto-claude/merge/auto_merger/merger.py b/apps/backend/merge/auto_merger/merger.py
similarity index 100%
rename from auto-claude/merge/auto_merger/merger.py
rename to apps/backend/merge/auto_merger/merger.py
diff --git a/auto-claude/merge/auto_merger/strategies/__init__.py b/apps/backend/merge/auto_merger/strategies/__init__.py
similarity index 100%
rename from auto-claude/merge/auto_merger/strategies/__init__.py
rename to apps/backend/merge/auto_merger/strategies/__init__.py
diff --git a/auto-claude/merge/auto_merger/strategies/append_strategy.py b/apps/backend/merge/auto_merger/strategies/append_strategy.py
similarity index 100%
rename from auto-claude/merge/auto_merger/strategies/append_strategy.py
rename to apps/backend/merge/auto_merger/strategies/append_strategy.py
diff --git a/auto-claude/merge/auto_merger/strategies/base_strategy.py b/apps/backend/merge/auto_merger/strategies/base_strategy.py
similarity index 100%
rename from auto-claude/merge/auto_merger/strategies/base_strategy.py
rename to apps/backend/merge/auto_merger/strategies/base_strategy.py
diff --git a/auto-claude/merge/auto_merger/strategies/hooks_strategy.py b/apps/backend/merge/auto_merger/strategies/hooks_strategy.py
similarity index 100%
rename from auto-claude/merge/auto_merger/strategies/hooks_strategy.py
rename to apps/backend/merge/auto_merger/strategies/hooks_strategy.py
diff --git a/auto-claude/merge/auto_merger/strategies/import_strategy.py b/apps/backend/merge/auto_merger/strategies/import_strategy.py
similarity index 100%
rename from auto-claude/merge/auto_merger/strategies/import_strategy.py
rename to apps/backend/merge/auto_merger/strategies/import_strategy.py
diff --git a/auto-claude/merge/auto_merger/strategies/ordering_strategy.py b/apps/backend/merge/auto_merger/strategies/ordering_strategy.py
similarity index 100%
rename from auto-claude/merge/auto_merger/strategies/ordering_strategy.py
rename to apps/backend/merge/auto_merger/strategies/ordering_strategy.py
diff --git a/auto-claude/merge/auto_merger/strategies/props_strategy.py b/apps/backend/merge/auto_merger/strategies/props_strategy.py
similarity index 100%
rename from auto-claude/merge/auto_merger/strategies/props_strategy.py
rename to apps/backend/merge/auto_merger/strategies/props_strategy.py
diff --git a/auto-claude/merge/compatibility_rules.py b/apps/backend/merge/compatibility_rules.py
similarity index 100%
rename from auto-claude/merge/compatibility_rules.py
rename to apps/backend/merge/compatibility_rules.py
diff --git a/auto-claude/merge/conflict_analysis.py b/apps/backend/merge/conflict_analysis.py
similarity index 100%
rename from auto-claude/merge/conflict_analysis.py
rename to apps/backend/merge/conflict_analysis.py
diff --git a/auto-claude/merge/conflict_detector.py b/apps/backend/merge/conflict_detector.py
similarity index 100%
rename from auto-claude/merge/conflict_detector.py
rename to apps/backend/merge/conflict_detector.py
diff --git a/auto-claude/merge/conflict_explanation.py b/apps/backend/merge/conflict_explanation.py
similarity index 100%
rename from auto-claude/merge/conflict_explanation.py
rename to apps/backend/merge/conflict_explanation.py
diff --git a/auto-claude/merge/conflict_resolver.py b/apps/backend/merge/conflict_resolver.py
similarity index 100%
rename from auto-claude/merge/conflict_resolver.py
rename to apps/backend/merge/conflict_resolver.py
diff --git a/auto-claude/merge/file_evolution.py b/apps/backend/merge/file_evolution.py
similarity index 100%
rename from auto-claude/merge/file_evolution.py
rename to apps/backend/merge/file_evolution.py
diff --git a/auto-claude/merge/file_evolution/__init__.py b/apps/backend/merge/file_evolution/__init__.py
similarity index 100%
rename from auto-claude/merge/file_evolution/__init__.py
rename to apps/backend/merge/file_evolution/__init__.py
diff --git a/auto-claude/merge/file_evolution/baseline_capture.py b/apps/backend/merge/file_evolution/baseline_capture.py
similarity index 100%
rename from auto-claude/merge/file_evolution/baseline_capture.py
rename to apps/backend/merge/file_evolution/baseline_capture.py
diff --git a/auto-claude/merge/file_evolution/evolution_queries.py b/apps/backend/merge/file_evolution/evolution_queries.py
similarity index 100%
rename from auto-claude/merge/file_evolution/evolution_queries.py
rename to apps/backend/merge/file_evolution/evolution_queries.py
diff --git a/auto-claude/merge/file_evolution/modification_tracker.py b/apps/backend/merge/file_evolution/modification_tracker.py
similarity index 100%
rename from auto-claude/merge/file_evolution/modification_tracker.py
rename to apps/backend/merge/file_evolution/modification_tracker.py
diff --git a/auto-claude/merge/file_evolution/storage.py b/apps/backend/merge/file_evolution/storage.py
similarity index 100%
rename from auto-claude/merge/file_evolution/storage.py
rename to apps/backend/merge/file_evolution/storage.py
diff --git a/auto-claude/merge/file_evolution/tracker.py b/apps/backend/merge/file_evolution/tracker.py
similarity index 100%
rename from auto-claude/merge/file_evolution/tracker.py
rename to apps/backend/merge/file_evolution/tracker.py
diff --git a/auto-claude/merge/file_merger.py b/apps/backend/merge/file_merger.py
similarity index 100%
rename from auto-claude/merge/file_merger.py
rename to apps/backend/merge/file_merger.py
diff --git a/auto-claude/merge/file_timeline.py b/apps/backend/merge/file_timeline.py
similarity index 100%
rename from auto-claude/merge/file_timeline.py
rename to apps/backend/merge/file_timeline.py
diff --git a/auto-claude/merge/git_utils.py b/apps/backend/merge/git_utils.py
similarity index 100%
rename from auto-claude/merge/git_utils.py
rename to apps/backend/merge/git_utils.py
diff --git a/auto-claude/merge/hooks/post-commit b/apps/backend/merge/hooks/post-commit
old mode 100755
new mode 100644
similarity index 100%
rename from auto-claude/merge/hooks/post-commit
rename to apps/backend/merge/hooks/post-commit
diff --git a/auto-claude/merge/install_hook.py b/apps/backend/merge/install_hook.py
similarity index 100%
rename from auto-claude/merge/install_hook.py
rename to apps/backend/merge/install_hook.py
diff --git a/auto-claude/merge/merge_pipeline.py b/apps/backend/merge/merge_pipeline.py
similarity index 100%
rename from auto-claude/merge/merge_pipeline.py
rename to apps/backend/merge/merge_pipeline.py
diff --git a/auto-claude/merge/models.py b/apps/backend/merge/models.py
similarity index 100%
rename from auto-claude/merge/models.py
rename to apps/backend/merge/models.py
diff --git a/auto-claude/merge/orchestrator.py b/apps/backend/merge/orchestrator.py
similarity index 100%
rename from auto-claude/merge/orchestrator.py
rename to apps/backend/merge/orchestrator.py
diff --git a/auto-claude/merge/prompts.py b/apps/backend/merge/prompts.py
similarity index 100%
rename from auto-claude/merge/prompts.py
rename to apps/backend/merge/prompts.py
diff --git a/auto-claude/merge/semantic_analysis/__init__.py b/apps/backend/merge/semantic_analysis/__init__.py
similarity index 100%
rename from auto-claude/merge/semantic_analysis/__init__.py
rename to apps/backend/merge/semantic_analysis/__init__.py
diff --git a/auto-claude/merge/semantic_analysis/comparison.py b/apps/backend/merge/semantic_analysis/comparison.py
similarity index 100%
rename from auto-claude/merge/semantic_analysis/comparison.py
rename to apps/backend/merge/semantic_analysis/comparison.py
diff --git a/auto-claude/merge/semantic_analysis/js_analyzer.py b/apps/backend/merge/semantic_analysis/js_analyzer.py
similarity index 100%
rename from auto-claude/merge/semantic_analysis/js_analyzer.py
rename to apps/backend/merge/semantic_analysis/js_analyzer.py
diff --git a/auto-claude/merge/semantic_analysis/models.py b/apps/backend/merge/semantic_analysis/models.py
similarity index 100%
rename from auto-claude/merge/semantic_analysis/models.py
rename to apps/backend/merge/semantic_analysis/models.py
diff --git a/auto-claude/merge/semantic_analysis/python_analyzer.py b/apps/backend/merge/semantic_analysis/python_analyzer.py
similarity index 100%
rename from auto-claude/merge/semantic_analysis/python_analyzer.py
rename to apps/backend/merge/semantic_analysis/python_analyzer.py
diff --git a/auto-claude/merge/semantic_analysis/regex_analyzer.py b/apps/backend/merge/semantic_analysis/regex_analyzer.py
similarity index 100%
rename from auto-claude/merge/semantic_analysis/regex_analyzer.py
rename to apps/backend/merge/semantic_analysis/regex_analyzer.py
diff --git a/auto-claude/merge/semantic_analyzer.py b/apps/backend/merge/semantic_analyzer.py
similarity index 100%
rename from auto-claude/merge/semantic_analyzer.py
rename to apps/backend/merge/semantic_analyzer.py
diff --git a/auto-claude/merge/timeline_git.py b/apps/backend/merge/timeline_git.py
similarity index 100%
rename from auto-claude/merge/timeline_git.py
rename to apps/backend/merge/timeline_git.py
diff --git a/auto-claude/merge/timeline_models.py b/apps/backend/merge/timeline_models.py
similarity index 100%
rename from auto-claude/merge/timeline_models.py
rename to apps/backend/merge/timeline_models.py
diff --git a/auto-claude/merge/timeline_persistence.py b/apps/backend/merge/timeline_persistence.py
similarity index 100%
rename from auto-claude/merge/timeline_persistence.py
rename to apps/backend/merge/timeline_persistence.py
diff --git a/auto-claude/merge/timeline_tracker.py b/apps/backend/merge/timeline_tracker.py
similarity index 100%
rename from auto-claude/merge/timeline_tracker.py
rename to apps/backend/merge/timeline_tracker.py
diff --git a/auto-claude/merge/tracker_cli.py b/apps/backend/merge/tracker_cli.py
similarity index 100%
rename from auto-claude/merge/tracker_cli.py
rename to apps/backend/merge/tracker_cli.py
diff --git a/auto-claude/merge/types.py b/apps/backend/merge/types.py
similarity index 100%
rename from auto-claude/merge/types.py
rename to apps/backend/merge/types.py
diff --git a/auto-claude/ollama_model_detector.py b/apps/backend/ollama_model_detector.py
similarity index 100%
rename from auto-claude/ollama_model_detector.py
rename to apps/backend/ollama_model_detector.py
diff --git a/auto-claude/phase_config.py b/apps/backend/phase_config.py
similarity index 100%
rename from auto-claude/phase_config.py
rename to apps/backend/phase_config.py
diff --git a/auto-claude/planner_lib/__init__.py b/apps/backend/planner_lib/__init__.py
similarity index 100%
rename from auto-claude/planner_lib/__init__.py
rename to apps/backend/planner_lib/__init__.py
diff --git a/auto-claude/planner_lib/context.py b/apps/backend/planner_lib/context.py
similarity index 100%
rename from auto-claude/planner_lib/context.py
rename to apps/backend/planner_lib/context.py
diff --git a/auto-claude/planner_lib/generators.py b/apps/backend/planner_lib/generators.py
similarity index 100%
rename from auto-claude/planner_lib/generators.py
rename to apps/backend/planner_lib/generators.py
diff --git a/auto-claude/planner_lib/main.py b/apps/backend/planner_lib/main.py
similarity index 100%
rename from auto-claude/planner_lib/main.py
rename to apps/backend/planner_lib/main.py
diff --git a/auto-claude/planner_lib/models.py b/apps/backend/planner_lib/models.py
similarity index 100%
rename from auto-claude/planner_lib/models.py
rename to apps/backend/planner_lib/models.py
diff --git a/auto-claude/planner_lib/utils.py b/apps/backend/planner_lib/utils.py
similarity index 100%
rename from auto-claude/planner_lib/utils.py
rename to apps/backend/planner_lib/utils.py
diff --git a/auto-claude/prediction/__init__.py b/apps/backend/prediction/__init__.py
similarity index 100%
rename from auto-claude/prediction/__init__.py
rename to apps/backend/prediction/__init__.py
diff --git a/auto-claude/prediction/checklist_generator.py b/apps/backend/prediction/checklist_generator.py
similarity index 100%
rename from auto-claude/prediction/checklist_generator.py
rename to apps/backend/prediction/checklist_generator.py
diff --git a/auto-claude/prediction/formatter.py b/apps/backend/prediction/formatter.py
similarity index 100%
rename from auto-claude/prediction/formatter.py
rename to apps/backend/prediction/formatter.py
diff --git a/auto-claude/prediction/main.py b/apps/backend/prediction/main.py
similarity index 100%
rename from auto-claude/prediction/main.py
rename to apps/backend/prediction/main.py
diff --git a/auto-claude/prediction/memory_loader.py b/apps/backend/prediction/memory_loader.py
similarity index 100%
rename from auto-claude/prediction/memory_loader.py
rename to apps/backend/prediction/memory_loader.py
diff --git a/auto-claude/prediction/models.py b/apps/backend/prediction/models.py
similarity index 100%
rename from auto-claude/prediction/models.py
rename to apps/backend/prediction/models.py
diff --git a/auto-claude/prediction/patterns.py b/apps/backend/prediction/patterns.py
similarity index 100%
rename from auto-claude/prediction/patterns.py
rename to apps/backend/prediction/patterns.py
diff --git a/auto-claude/prediction/predictor.py b/apps/backend/prediction/predictor.py
similarity index 100%
rename from auto-claude/prediction/predictor.py
rename to apps/backend/prediction/predictor.py
diff --git a/auto-claude/prediction/risk_analyzer.py b/apps/backend/prediction/risk_analyzer.py
similarity index 100%
rename from auto-claude/prediction/risk_analyzer.py
rename to apps/backend/prediction/risk_analyzer.py
diff --git a/apps/backend/progress.py b/apps/backend/progress.py
new file mode 100644
index 00000000..5cc2afea
--- /dev/null
+++ b/apps/backend/progress.py
@@ -0,0 +1,36 @@
+"""
+Progress tracking module facade.
+
+Provides progress tracking utilities for build execution.
+Re-exports from core.progress for clean imports.
+"""
+
+from core.progress import (
+ count_subtasks,
+ count_subtasks_detailed,
+ format_duration,
+ get_current_phase,
+ get_next_subtask,
+ get_plan_summary,
+ get_progress_percentage,
+ is_build_complete,
+ print_build_complete_banner,
+ print_paused_banner,
+ print_progress_summary,
+ print_session_header,
+)
+
+__all__ = [
+ "count_subtasks",
+ "count_subtasks_detailed",
+ "format_duration",
+ "get_current_phase",
+ "get_next_subtask",
+ "get_plan_summary",
+ "get_progress_percentage",
+ "is_build_complete",
+ "print_build_complete_banner",
+ "print_paused_banner",
+ "print_progress_summary",
+ "print_session_header",
+]
diff --git a/auto-claude/project/__init__.py b/apps/backend/project/__init__.py
similarity index 100%
rename from auto-claude/project/__init__.py
rename to apps/backend/project/__init__.py
diff --git a/auto-claude/project/analyzer.py b/apps/backend/project/analyzer.py
similarity index 100%
rename from auto-claude/project/analyzer.py
rename to apps/backend/project/analyzer.py
diff --git a/auto-claude/project/command_registry.py b/apps/backend/project/command_registry.py
similarity index 100%
rename from auto-claude/project/command_registry.py
rename to apps/backend/project/command_registry.py
diff --git a/auto-claude/project/command_registry/README.md b/apps/backend/project/command_registry/README.md
similarity index 100%
rename from auto-claude/project/command_registry/README.md
rename to apps/backend/project/command_registry/README.md
diff --git a/auto-claude/project/command_registry/__init__.py b/apps/backend/project/command_registry/__init__.py
similarity index 100%
rename from auto-claude/project/command_registry/__init__.py
rename to apps/backend/project/command_registry/__init__.py
diff --git a/auto-claude/project/command_registry/base.py b/apps/backend/project/command_registry/base.py
similarity index 100%
rename from auto-claude/project/command_registry/base.py
rename to apps/backend/project/command_registry/base.py
diff --git a/auto-claude/project/command_registry/cloud.py b/apps/backend/project/command_registry/cloud.py
similarity index 100%
rename from auto-claude/project/command_registry/cloud.py
rename to apps/backend/project/command_registry/cloud.py
diff --git a/auto-claude/project/command_registry/code_quality.py b/apps/backend/project/command_registry/code_quality.py
similarity index 100%
rename from auto-claude/project/command_registry/code_quality.py
rename to apps/backend/project/command_registry/code_quality.py
diff --git a/auto-claude/project/command_registry/databases.py b/apps/backend/project/command_registry/databases.py
similarity index 100%
rename from auto-claude/project/command_registry/databases.py
rename to apps/backend/project/command_registry/databases.py
diff --git a/auto-claude/project/command_registry/frameworks.py b/apps/backend/project/command_registry/frameworks.py
similarity index 100%
rename from auto-claude/project/command_registry/frameworks.py
rename to apps/backend/project/command_registry/frameworks.py
diff --git a/auto-claude/project/command_registry/infrastructure.py b/apps/backend/project/command_registry/infrastructure.py
similarity index 100%
rename from auto-claude/project/command_registry/infrastructure.py
rename to apps/backend/project/command_registry/infrastructure.py
diff --git a/auto-claude/project/command_registry/languages.py b/apps/backend/project/command_registry/languages.py
similarity index 100%
rename from auto-claude/project/command_registry/languages.py
rename to apps/backend/project/command_registry/languages.py
diff --git a/auto-claude/project/command_registry/package_managers.py b/apps/backend/project/command_registry/package_managers.py
similarity index 100%
rename from auto-claude/project/command_registry/package_managers.py
rename to apps/backend/project/command_registry/package_managers.py
diff --git a/auto-claude/project/command_registry/version_managers.py b/apps/backend/project/command_registry/version_managers.py
similarity index 100%
rename from auto-claude/project/command_registry/version_managers.py
rename to apps/backend/project/command_registry/version_managers.py
diff --git a/auto-claude/project/config_parser.py b/apps/backend/project/config_parser.py
similarity index 100%
rename from auto-claude/project/config_parser.py
rename to apps/backend/project/config_parser.py
diff --git a/auto-claude/project/framework_detector.py b/apps/backend/project/framework_detector.py
similarity index 100%
rename from auto-claude/project/framework_detector.py
rename to apps/backend/project/framework_detector.py
diff --git a/auto-claude/project/models.py b/apps/backend/project/models.py
similarity index 100%
rename from auto-claude/project/models.py
rename to apps/backend/project/models.py
diff --git a/auto-claude/project/stack_detector.py b/apps/backend/project/stack_detector.py
similarity index 100%
rename from auto-claude/project/stack_detector.py
rename to apps/backend/project/stack_detector.py
diff --git a/auto-claude/project/structure_analyzer.py b/apps/backend/project/structure_analyzer.py
similarity index 100%
rename from auto-claude/project/structure_analyzer.py
rename to apps/backend/project/structure_analyzer.py
diff --git a/auto-claude/project_analyzer.py b/apps/backend/project_analyzer.py
similarity index 100%
rename from auto-claude/project_analyzer.py
rename to apps/backend/project_analyzer.py
diff --git a/auto-claude/prompt_generator.py b/apps/backend/prompt_generator.py
similarity index 100%
rename from auto-claude/prompt_generator.py
rename to apps/backend/prompt_generator.py
diff --git a/auto-claude/prompts.py b/apps/backend/prompts.py
similarity index 100%
rename from auto-claude/prompts.py
rename to apps/backend/prompts.py
diff --git a/auto-claude/prompts/coder.md b/apps/backend/prompts/coder.md
similarity index 100%
rename from auto-claude/prompts/coder.md
rename to apps/backend/prompts/coder.md
diff --git a/auto-claude/prompts/coder_recovery.md b/apps/backend/prompts/coder_recovery.md
similarity index 100%
rename from auto-claude/prompts/coder_recovery.md
rename to apps/backend/prompts/coder_recovery.md
diff --git a/auto-claude/prompts/competitor_analysis.md b/apps/backend/prompts/competitor_analysis.md
similarity index 100%
rename from auto-claude/prompts/competitor_analysis.md
rename to apps/backend/prompts/competitor_analysis.md
diff --git a/auto-claude/prompts/complexity_assessor.md b/apps/backend/prompts/complexity_assessor.md
similarity index 96%
rename from auto-claude/prompts/complexity_assessor.md
rename to apps/backend/prompts/complexity_assessor.md
index 5ff0f925..540534cf 100644
--- a/auto-claude/prompts/complexity_assessor.md
+++ b/apps/backend/prompts/complexity_assessor.md
@@ -588,7 +588,7 @@ START
### Example 5: Complex Feature Task
-**Task**: "Add Graphiti Memory Integration with FalkorDB as an optional layer controlled by .env variables using Docker Compose"
+**Task**: "Add Graphiti Memory Integration with LadybugDB (embedded database) as an optional layer controlled by .env variables"
**Assessment**:
```json
@@ -596,7 +596,7 @@ START
"complexity": "complex",
"workflow_type": "feature",
"confidence": 0.90,
- "reasoning": "Multiple integrations (Graphiti, FalkorDB), infrastructure changes (Docker Compose), and new architectural pattern (optional memory layer). Requires research for correct API usage and careful design.",
+ "reasoning": "Multiple integrations (Graphiti, LadybugDB), new architectural pattern (memory layer with embedded database). Requires research for correct API usage and careful design.",
"analysis": {
"scope": {
"estimated_files": 12,
@@ -605,21 +605,21 @@ START
"notes": "Memory integration will likely touch multiple parts of the system"
},
"integrations": {
- "external_services": ["Graphiti", "FalkorDB"],
- "new_dependencies": ["graphiti-core", "falkordb driver"],
+ "external_services": ["Graphiti", "LadybugDB"],
+ "new_dependencies": ["graphiti-core", "real_ladybug"],
"research_needed": true,
"notes": "Graphiti is a newer library, need to verify API patterns"
},
"infrastructure": {
- "docker_changes": true,
+ "docker_changes": false,
"database_changes": true,
"config_changes": true,
- "notes": "FalkorDB requires Docker container, new env vars needed"
+ "notes": "LadybugDB is embedded, no Docker needed, new env vars required"
},
"knowledge": {
"patterns_exist": false,
"research_required": true,
- "unfamiliar_tech": ["graphiti-core", "FalkorDB"],
+ "unfamiliar_tech": ["graphiti-core", "LadybugDB"],
"notes": "No existing graph database patterns in codebase"
},
"risk": {
@@ -632,7 +632,7 @@ START
"flags": {
"needs_research": true,
"needs_self_critique": true,
- "needs_infrastructure_setup": true
+ "needs_infrastructure_setup": false
},
"validation_recommendations": {
"risk_level": "high",
@@ -640,8 +640,8 @@ START
"minimal_mode": false,
"test_types_required": ["unit", "integration", "e2e"],
"security_scan_required": true,
- "staging_deployment_required": true,
- "reasoning": "Database integration with new dependencies requires full test coverage. Security scan for API key handling. Staging deployment to verify Docker container orchestration."
+ "staging_deployment_required": false,
+ "reasoning": "Database integration with new dependencies requires full test coverage. Security scan for API key handling. No staging deployment needed since embedded database doesn't require infrastructure setup."
}
}
```
diff --git a/auto-claude/prompts/followup_planner.md b/apps/backend/prompts/followup_planner.md
similarity index 100%
rename from auto-claude/prompts/followup_planner.md
rename to apps/backend/prompts/followup_planner.md
diff --git a/auto-claude/prompts/ideation_code_improvements.md b/apps/backend/prompts/ideation_code_improvements.md
similarity index 100%
rename from auto-claude/prompts/ideation_code_improvements.md
rename to apps/backend/prompts/ideation_code_improvements.md
diff --git a/auto-claude/prompts/ideation_code_quality.md b/apps/backend/prompts/ideation_code_quality.md
similarity index 100%
rename from auto-claude/prompts/ideation_code_quality.md
rename to apps/backend/prompts/ideation_code_quality.md
diff --git a/auto-claude/prompts/ideation_documentation.md b/apps/backend/prompts/ideation_documentation.md
similarity index 100%
rename from auto-claude/prompts/ideation_documentation.md
rename to apps/backend/prompts/ideation_documentation.md
diff --git a/auto-claude/prompts/ideation_performance.md b/apps/backend/prompts/ideation_performance.md
similarity index 100%
rename from auto-claude/prompts/ideation_performance.md
rename to apps/backend/prompts/ideation_performance.md
diff --git a/auto-claude/prompts/ideation_security.md b/apps/backend/prompts/ideation_security.md
similarity index 100%
rename from auto-claude/prompts/ideation_security.md
rename to apps/backend/prompts/ideation_security.md
diff --git a/auto-claude/prompts/ideation_ui_ux.md b/apps/backend/prompts/ideation_ui_ux.md
similarity index 100%
rename from auto-claude/prompts/ideation_ui_ux.md
rename to apps/backend/prompts/ideation_ui_ux.md
diff --git a/auto-claude/prompts/insight_extractor.md b/apps/backend/prompts/insight_extractor.md
similarity index 100%
rename from auto-claude/prompts/insight_extractor.md
rename to apps/backend/prompts/insight_extractor.md
diff --git a/auto-claude/prompts/mcp_tools/api_validation.md b/apps/backend/prompts/mcp_tools/api_validation.md
similarity index 100%
rename from auto-claude/prompts/mcp_tools/api_validation.md
rename to apps/backend/prompts/mcp_tools/api_validation.md
diff --git a/auto-claude/prompts/mcp_tools/database_validation.md b/apps/backend/prompts/mcp_tools/database_validation.md
similarity index 100%
rename from auto-claude/prompts/mcp_tools/database_validation.md
rename to apps/backend/prompts/mcp_tools/database_validation.md
diff --git a/auto-claude/prompts/mcp_tools/electron_validation.md b/apps/backend/prompts/mcp_tools/electron_validation.md
similarity index 100%
rename from auto-claude/prompts/mcp_tools/electron_validation.md
rename to apps/backend/prompts/mcp_tools/electron_validation.md
diff --git a/auto-claude/prompts/mcp_tools/puppeteer_browser.md b/apps/backend/prompts/mcp_tools/puppeteer_browser.md
similarity index 100%
rename from auto-claude/prompts/mcp_tools/puppeteer_browser.md
rename to apps/backend/prompts/mcp_tools/puppeteer_browser.md
diff --git a/auto-claude/prompts/planner.md b/apps/backend/prompts/planner.md
similarity index 100%
rename from auto-claude/prompts/planner.md
rename to apps/backend/prompts/planner.md
diff --git a/auto-claude/prompts/qa_fixer.md b/apps/backend/prompts/qa_fixer.md
similarity index 100%
rename from auto-claude/prompts/qa_fixer.md
rename to apps/backend/prompts/qa_fixer.md
diff --git a/auto-claude/prompts/qa_reviewer.md b/apps/backend/prompts/qa_reviewer.md
similarity index 100%
rename from auto-claude/prompts/qa_reviewer.md
rename to apps/backend/prompts/qa_reviewer.md
diff --git a/auto-claude/prompts/roadmap_discovery.md b/apps/backend/prompts/roadmap_discovery.md
similarity index 100%
rename from auto-claude/prompts/roadmap_discovery.md
rename to apps/backend/prompts/roadmap_discovery.md
diff --git a/auto-claude/prompts/roadmap_features.md b/apps/backend/prompts/roadmap_features.md
similarity index 100%
rename from auto-claude/prompts/roadmap_features.md
rename to apps/backend/prompts/roadmap_features.md
diff --git a/auto-claude/prompts/spec_critic.md b/apps/backend/prompts/spec_critic.md
similarity index 97%
rename from auto-claude/prompts/spec_critic.md
rename to apps/backend/prompts/spec_critic.md
index 2f5a1f3c..2f0f08fb 100644
--- a/auto-claude/prompts/spec_critic.md
+++ b/apps/backend/prompts/spec_critic.md
@@ -130,8 +130,8 @@ Create a list of all issues found:
ISSUES FOUND:
1. [SEVERITY: HIGH] Package name incorrect
- - Spec says: "graphiti-core[falkordb]"
- - Research says: "graphiti-core-falkordb"
+ - Spec says: "graphiti-core real_ladybug"
+ - Research says: "graphiti-core" with separate "real_ladybug" dependency
- Location: Line 45, Requirements section
2. [SEVERITY: MEDIUM] Missing edge case
@@ -156,7 +156,7 @@ cat spec.md
# Apply fixes using edit commands
# Example: Fix package name
-sed -i 's/graphiti-core\[falkordb\]/graphiti-core-falkordb/g' spec.md
+sed -i 's/graphiti-core real_ladybug/graphiti-core\nreal_ladybug/g' spec.md
# Or rewrite sections as needed
```
diff --git a/auto-claude/prompts/spec_gatherer.md b/apps/backend/prompts/spec_gatherer.md
similarity index 100%
rename from auto-claude/prompts/spec_gatherer.md
rename to apps/backend/prompts/spec_gatherer.md
diff --git a/auto-claude/prompts/spec_quick.md b/apps/backend/prompts/spec_quick.md
similarity index 100%
rename from auto-claude/prompts/spec_quick.md
rename to apps/backend/prompts/spec_quick.md
diff --git a/auto-claude/prompts/spec_researcher.md b/apps/backend/prompts/spec_researcher.md
similarity index 95%
rename from auto-claude/prompts/spec_researcher.md
rename to apps/backend/prompts/spec_researcher.md
index f9793e0a..9d3af8b1 100644
--- a/auto-claude/prompts/spec_researcher.md
+++ b/apps/backend/prompts/spec_researcher.md
@@ -290,7 +290,7 @@ Input: {
"type": "library",
"verified_package": {
"name": "graphiti-core",
- "install_command": "pip install graphiti-core[falkordb]",
+ "install_command": "pip install graphiti-core",
"version": ">=0.5.0",
"verified": true
},
@@ -308,16 +308,16 @@ Input: {
},
"configuration": {
"env_vars": ["OPENAI_API_KEY"],
- "dependencies": ["neo4j or falkordb driver"]
+ "dependencies": ["real_ladybug"]
},
"infrastructure": {
- "requires_docker": true,
- "docker_image": "falkordb/falkordb:latest",
- "ports": [6379, 3000]
+ "requires_docker": false,
+ "embedded_database": "LadybugDB"
},
"gotchas": [
"Requires OpenAI API key for embeddings",
- "Must call build_indices_and_constraints() before use"
+ "Must call build_indices_and_constraints() before use",
+ "LadybugDB is embedded - no separate database server needed"
],
"research_sources": [
"Context7 MCP: /zep/graphiti",
@@ -328,7 +328,7 @@ Input: {
],
"unverified_claims": [],
"recommendations": [
- "Consider FalkorDB over Neo4j for simpler local development"
+ "LadybugDB is embedded and requires no Docker or separate database setup"
],
"context7_libraries_used": ["/zep/graphiti"],
"created_at": "2024-12-10T12:00:00Z"
diff --git a/auto-claude/prompts/spec_writer.md b/apps/backend/prompts/spec_writer.md
similarity index 100%
rename from auto-claude/prompts/spec_writer.md
rename to apps/backend/prompts/spec_writer.md
diff --git a/auto-claude/prompts/validation_fixer.md b/apps/backend/prompts/validation_fixer.md
similarity index 100%
rename from auto-claude/prompts/validation_fixer.md
rename to apps/backend/prompts/validation_fixer.md
diff --git a/auto-claude/prompts_pkg/__init__.py b/apps/backend/prompts_pkg/__init__.py
similarity index 100%
rename from auto-claude/prompts_pkg/__init__.py
rename to apps/backend/prompts_pkg/__init__.py
diff --git a/auto-claude/prompts_pkg/project_context.py b/apps/backend/prompts_pkg/project_context.py
similarity index 100%
rename from auto-claude/prompts_pkg/project_context.py
rename to apps/backend/prompts_pkg/project_context.py
diff --git a/auto-claude/prompts_pkg/prompt_generator.py b/apps/backend/prompts_pkg/prompt_generator.py
similarity index 100%
rename from auto-claude/prompts_pkg/prompt_generator.py
rename to apps/backend/prompts_pkg/prompt_generator.py
diff --git a/auto-claude/prompts_pkg/prompts.py b/apps/backend/prompts_pkg/prompts.py
similarity index 100%
rename from auto-claude/prompts_pkg/prompts.py
rename to apps/backend/prompts_pkg/prompts.py
diff --git a/auto-claude/qa/__init__.py b/apps/backend/qa/__init__.py
similarity index 100%
rename from auto-claude/qa/__init__.py
rename to apps/backend/qa/__init__.py
diff --git a/auto-claude/qa/criteria.py b/apps/backend/qa/criteria.py
similarity index 100%
rename from auto-claude/qa/criteria.py
rename to apps/backend/qa/criteria.py
diff --git a/auto-claude/qa/fixer.py b/apps/backend/qa/fixer.py
similarity index 100%
rename from auto-claude/qa/fixer.py
rename to apps/backend/qa/fixer.py
diff --git a/auto-claude/qa/loop.py b/apps/backend/qa/loop.py
similarity index 100%
rename from auto-claude/qa/loop.py
rename to apps/backend/qa/loop.py
diff --git a/auto-claude/qa/qa_loop.py b/apps/backend/qa/qa_loop.py
similarity index 100%
rename from auto-claude/qa/qa_loop.py
rename to apps/backend/qa/qa_loop.py
diff --git a/auto-claude/qa/report.py b/apps/backend/qa/report.py
similarity index 100%
rename from auto-claude/qa/report.py
rename to apps/backend/qa/report.py
diff --git a/auto-claude/qa/reviewer.py b/apps/backend/qa/reviewer.py
similarity index 100%
rename from auto-claude/qa/reviewer.py
rename to apps/backend/qa/reviewer.py
diff --git a/auto-claude/qa_loop.py b/apps/backend/qa_loop.py
similarity index 84%
rename from auto-claude/qa_loop.py
rename to apps/backend/qa_loop.py
index 2fe364c1..65100226 100644
--- a/auto-claude/qa_loop.py
+++ b/apps/backend/qa_loop.py
@@ -1,8 +1,12 @@
-"""Backward compatibility shim - import from qa package instead."""
+"""
+QA loop module facade.
+
+Provides QA validation loop functionality.
+Re-exports from qa package for clean imports.
+"""
from qa import (
ISSUE_SIMILARITY_THRESHOLD,
- # Configuration
MAX_QA_ITERATIONS,
RECURRING_ISSUE_THRESHOLD,
_issue_similarity,
@@ -10,7 +14,6 @@ from qa import (
check_test_discovery,
create_manual_test_plan,
escalate_to_human,
- # Report & tracking
get_iteration_history,
get_qa_iteration_count,
get_qa_signoff_status,
@@ -20,15 +23,12 @@ from qa import (
is_no_test_project,
is_qa_approved,
is_qa_rejected,
- # Criteria & status
load_implementation_plan,
load_qa_fixer_prompt,
- # Agent sessions
print_qa_status,
record_iteration,
run_qa_agent_session,
run_qa_fixer_session,
- # Main loop
run_qa_validation_loop,
save_implementation_plan,
should_run_fixes,
@@ -36,13 +36,10 @@ from qa import (
)
__all__ = [
- # Configuration
"MAX_QA_ITERATIONS",
"RECURRING_ISSUE_THRESHOLD",
"ISSUE_SIMILARITY_THRESHOLD",
- # Main loop
"run_qa_validation_loop",
- # Criteria & status
"load_implementation_plan",
"save_implementation_plan",
"get_qa_signoff_status",
@@ -53,7 +50,6 @@ __all__ = [
"should_run_qa",
"should_run_fixes",
"print_qa_status",
- # Report & tracking
"get_iteration_history",
"record_iteration",
"has_recurring_issues",
@@ -64,7 +60,6 @@ __all__ = [
"is_no_test_project",
"_normalize_issue_key",
"_issue_similarity",
- # Agent sessions
"run_qa_agent_session",
"load_qa_fixer_prompt",
"run_qa_fixer_session",
diff --git a/auto-claude/query_memory.py b/apps/backend/query_memory.py
similarity index 100%
rename from auto-claude/query_memory.py
rename to apps/backend/query_memory.py
diff --git a/auto-claude/recovery.py b/apps/backend/recovery.py
similarity index 100%
rename from auto-claude/recovery.py
rename to apps/backend/recovery.py
diff --git a/auto-claude/requirements.txt b/apps/backend/requirements.txt
similarity index 100%
rename from auto-claude/requirements.txt
rename to apps/backend/requirements.txt
diff --git a/auto-claude/review/__init__.py b/apps/backend/review/__init__.py
similarity index 100%
rename from auto-claude/review/__init__.py
rename to apps/backend/review/__init__.py
diff --git a/auto-claude/review/diff_analyzer.py b/apps/backend/review/diff_analyzer.py
similarity index 100%
rename from auto-claude/review/diff_analyzer.py
rename to apps/backend/review/diff_analyzer.py
diff --git a/auto-claude/review/formatters.py b/apps/backend/review/formatters.py
similarity index 100%
rename from auto-claude/review/formatters.py
rename to apps/backend/review/formatters.py
diff --git a/auto-claude/review/main.py b/apps/backend/review/main.py
similarity index 100%
rename from auto-claude/review/main.py
rename to apps/backend/review/main.py
diff --git a/auto-claude/review/reviewer.py b/apps/backend/review/reviewer.py
similarity index 100%
rename from auto-claude/review/reviewer.py
rename to apps/backend/review/reviewer.py
diff --git a/auto-claude/review/state.py b/apps/backend/review/state.py
similarity index 100%
rename from auto-claude/review/state.py
rename to apps/backend/review/state.py
diff --git a/auto-claude/risk_classifier.py b/apps/backend/risk_classifier.py
similarity index 100%
rename from auto-claude/risk_classifier.py
rename to apps/backend/risk_classifier.py
diff --git a/auto-claude/run.py b/apps/backend/run.py
similarity index 100%
rename from auto-claude/run.py
rename to apps/backend/run.py
diff --git a/auto-claude/runners/__init__.py b/apps/backend/runners/__init__.py
similarity index 100%
rename from auto-claude/runners/__init__.py
rename to apps/backend/runners/__init__.py
diff --git a/auto-claude/runners/ai_analyzer/EXAMPLES.md b/apps/backend/runners/ai_analyzer/EXAMPLES.md
similarity index 100%
rename from auto-claude/runners/ai_analyzer/EXAMPLES.md
rename to apps/backend/runners/ai_analyzer/EXAMPLES.md
diff --git a/auto-claude/runners/ai_analyzer/README.md b/apps/backend/runners/ai_analyzer/README.md
similarity index 100%
rename from auto-claude/runners/ai_analyzer/README.md
rename to apps/backend/runners/ai_analyzer/README.md
diff --git a/auto-claude/runners/ai_analyzer/__init__.py b/apps/backend/runners/ai_analyzer/__init__.py
similarity index 100%
rename from auto-claude/runners/ai_analyzer/__init__.py
rename to apps/backend/runners/ai_analyzer/__init__.py
diff --git a/auto-claude/runners/ai_analyzer/analyzers.py b/apps/backend/runners/ai_analyzer/analyzers.py
similarity index 100%
rename from auto-claude/runners/ai_analyzer/analyzers.py
rename to apps/backend/runners/ai_analyzer/analyzers.py
diff --git a/auto-claude/runners/ai_analyzer/cache_manager.py b/apps/backend/runners/ai_analyzer/cache_manager.py
similarity index 100%
rename from auto-claude/runners/ai_analyzer/cache_manager.py
rename to apps/backend/runners/ai_analyzer/cache_manager.py
diff --git a/auto-claude/runners/ai_analyzer/claude_client.py b/apps/backend/runners/ai_analyzer/claude_client.py
similarity index 100%
rename from auto-claude/runners/ai_analyzer/claude_client.py
rename to apps/backend/runners/ai_analyzer/claude_client.py
diff --git a/auto-claude/runners/ai_analyzer/cost_estimator.py b/apps/backend/runners/ai_analyzer/cost_estimator.py
similarity index 100%
rename from auto-claude/runners/ai_analyzer/cost_estimator.py
rename to apps/backend/runners/ai_analyzer/cost_estimator.py
diff --git a/auto-claude/runners/ai_analyzer/models.py b/apps/backend/runners/ai_analyzer/models.py
similarity index 100%
rename from auto-claude/runners/ai_analyzer/models.py
rename to apps/backend/runners/ai_analyzer/models.py
diff --git a/auto-claude/runners/ai_analyzer/result_parser.py b/apps/backend/runners/ai_analyzer/result_parser.py
similarity index 100%
rename from auto-claude/runners/ai_analyzer/result_parser.py
rename to apps/backend/runners/ai_analyzer/result_parser.py
diff --git a/auto-claude/runners/ai_analyzer/runner.py b/apps/backend/runners/ai_analyzer/runner.py
similarity index 100%
rename from auto-claude/runners/ai_analyzer/runner.py
rename to apps/backend/runners/ai_analyzer/runner.py
diff --git a/auto-claude/runners/ai_analyzer/summary_printer.py b/apps/backend/runners/ai_analyzer/summary_printer.py
similarity index 100%
rename from auto-claude/runners/ai_analyzer/summary_printer.py
rename to apps/backend/runners/ai_analyzer/summary_printer.py
diff --git a/auto-claude/runners/ai_analyzer_runner.py b/apps/backend/runners/ai_analyzer_runner.py
old mode 100755
new mode 100644
similarity index 100%
rename from auto-claude/runners/ai_analyzer_runner.py
rename to apps/backend/runners/ai_analyzer_runner.py
diff --git a/auto-claude/runners/ideation_runner.py b/apps/backend/runners/ideation_runner.py
similarity index 100%
rename from auto-claude/runners/ideation_runner.py
rename to apps/backend/runners/ideation_runner.py
diff --git a/auto-claude/runners/insights_runner.py b/apps/backend/runners/insights_runner.py
similarity index 100%
rename from auto-claude/runners/insights_runner.py
rename to apps/backend/runners/insights_runner.py
diff --git a/auto-claude/runners/roadmap/__init__.py b/apps/backend/runners/roadmap/__init__.py
similarity index 100%
rename from auto-claude/runners/roadmap/__init__.py
rename to apps/backend/runners/roadmap/__init__.py
diff --git a/auto-claude/runners/roadmap/competitor_analyzer.py b/apps/backend/runners/roadmap/competitor_analyzer.py
similarity index 100%
rename from auto-claude/runners/roadmap/competitor_analyzer.py
rename to apps/backend/runners/roadmap/competitor_analyzer.py
diff --git a/auto-claude/runners/roadmap/executor.py b/apps/backend/runners/roadmap/executor.py
similarity index 100%
rename from auto-claude/runners/roadmap/executor.py
rename to apps/backend/runners/roadmap/executor.py
diff --git a/auto-claude/runners/roadmap/graph_integration.py b/apps/backend/runners/roadmap/graph_integration.py
similarity index 100%
rename from auto-claude/runners/roadmap/graph_integration.py
rename to apps/backend/runners/roadmap/graph_integration.py
diff --git a/auto-claude/runners/roadmap/models.py b/apps/backend/runners/roadmap/models.py
similarity index 100%
rename from auto-claude/runners/roadmap/models.py
rename to apps/backend/runners/roadmap/models.py
diff --git a/auto-claude/runners/roadmap/orchestrator.py b/apps/backend/runners/roadmap/orchestrator.py
similarity index 100%
rename from auto-claude/runners/roadmap/orchestrator.py
rename to apps/backend/runners/roadmap/orchestrator.py
diff --git a/auto-claude/runners/roadmap/phases.py b/apps/backend/runners/roadmap/phases.py
similarity index 100%
rename from auto-claude/runners/roadmap/phases.py
rename to apps/backend/runners/roadmap/phases.py
diff --git a/auto-claude/runners/roadmap/project_index.json b/apps/backend/runners/roadmap/project_index.json
similarity index 100%
rename from auto-claude/runners/roadmap/project_index.json
rename to apps/backend/runners/roadmap/project_index.json
diff --git a/auto-claude/runners/roadmap_runner.py b/apps/backend/runners/roadmap_runner.py
similarity index 100%
rename from auto-claude/runners/roadmap_runner.py
rename to apps/backend/runners/roadmap_runner.py
diff --git a/auto-claude/runners/spec_runner.py b/apps/backend/runners/spec_runner.py
similarity index 100%
rename from auto-claude/runners/spec_runner.py
rename to apps/backend/runners/spec_runner.py
diff --git a/auto-claude/scan-for-secrets b/apps/backend/scan-for-secrets
old mode 100755
new mode 100644
similarity index 100%
rename from auto-claude/scan-for-secrets
rename to apps/backend/scan-for-secrets
diff --git a/auto-claude/scan_secrets.py b/apps/backend/scan_secrets.py
similarity index 100%
rename from auto-claude/scan_secrets.py
rename to apps/backend/scan_secrets.py
diff --git a/auto-claude/security.py b/apps/backend/security.py
similarity index 100%
rename from auto-claude/security.py
rename to apps/backend/security.py
diff --git a/auto-claude/security/__init__.py b/apps/backend/security/__init__.py
similarity index 100%
rename from auto-claude/security/__init__.py
rename to apps/backend/security/__init__.py
diff --git a/auto-claude/security/database_validators.py b/apps/backend/security/database_validators.py
similarity index 100%
rename from auto-claude/security/database_validators.py
rename to apps/backend/security/database_validators.py
diff --git a/auto-claude/security/filesystem_validators.py b/apps/backend/security/filesystem_validators.py
similarity index 100%
rename from auto-claude/security/filesystem_validators.py
rename to apps/backend/security/filesystem_validators.py
diff --git a/auto-claude/security/git_validators.py b/apps/backend/security/git_validators.py
similarity index 100%
rename from auto-claude/security/git_validators.py
rename to apps/backend/security/git_validators.py
diff --git a/auto-claude/security/hooks.py b/apps/backend/security/hooks.py
similarity index 100%
rename from auto-claude/security/hooks.py
rename to apps/backend/security/hooks.py
diff --git a/auto-claude/security/main.py b/apps/backend/security/main.py
similarity index 100%
rename from auto-claude/security/main.py
rename to apps/backend/security/main.py
diff --git a/auto-claude/security/parser.py b/apps/backend/security/parser.py
similarity index 100%
rename from auto-claude/security/parser.py
rename to apps/backend/security/parser.py
diff --git a/auto-claude/security/process_validators.py b/apps/backend/security/process_validators.py
similarity index 100%
rename from auto-claude/security/process_validators.py
rename to apps/backend/security/process_validators.py
diff --git a/auto-claude/security/profile.py b/apps/backend/security/profile.py
similarity index 100%
rename from auto-claude/security/profile.py
rename to apps/backend/security/profile.py
diff --git a/auto-claude/security/scan_secrets.py b/apps/backend/security/scan_secrets.py
similarity index 100%
rename from auto-claude/security/scan_secrets.py
rename to apps/backend/security/scan_secrets.py
diff --git a/auto-claude/security/validation_models.py b/apps/backend/security/validation_models.py
similarity index 100%
rename from auto-claude/security/validation_models.py
rename to apps/backend/security/validation_models.py
diff --git a/auto-claude/security/validator.py b/apps/backend/security/validator.py
similarity index 100%
rename from auto-claude/security/validator.py
rename to apps/backend/security/validator.py
diff --git a/auto-claude/security/validator_registry.py b/apps/backend/security/validator_registry.py
similarity index 100%
rename from auto-claude/security/validator_registry.py
rename to apps/backend/security/validator_registry.py
diff --git a/auto-claude/security_scanner.py b/apps/backend/security_scanner.py
similarity index 100%
rename from auto-claude/security_scanner.py
rename to apps/backend/security_scanner.py
diff --git a/auto-claude/service_orchestrator.py b/apps/backend/service_orchestrator.py
similarity index 100%
rename from auto-claude/service_orchestrator.py
rename to apps/backend/service_orchestrator.py
diff --git a/auto-claude/services/__init__.py b/apps/backend/services/__init__.py
similarity index 100%
rename from auto-claude/services/__init__.py
rename to apps/backend/services/__init__.py
diff --git a/auto-claude/services/context.py b/apps/backend/services/context.py
similarity index 100%
rename from auto-claude/services/context.py
rename to apps/backend/services/context.py
diff --git a/auto-claude/services/orchestrator.py b/apps/backend/services/orchestrator.py
similarity index 100%
rename from auto-claude/services/orchestrator.py
rename to apps/backend/services/orchestrator.py
diff --git a/auto-claude/services/recovery.py b/apps/backend/services/recovery.py
similarity index 100%
rename from auto-claude/services/recovery.py
rename to apps/backend/services/recovery.py
diff --git a/auto-claude/spec/__init__.py b/apps/backend/spec/__init__.py
similarity index 100%
rename from auto-claude/spec/__init__.py
rename to apps/backend/spec/__init__.py
diff --git a/auto-claude/spec/compaction.py b/apps/backend/spec/compaction.py
similarity index 100%
rename from auto-claude/spec/compaction.py
rename to apps/backend/spec/compaction.py
diff --git a/auto-claude/spec/complexity.py b/apps/backend/spec/complexity.py
similarity index 100%
rename from auto-claude/spec/complexity.py
rename to apps/backend/spec/complexity.py
diff --git a/auto-claude/spec/context.py b/apps/backend/spec/context.py
similarity index 100%
rename from auto-claude/spec/context.py
rename to apps/backend/spec/context.py
diff --git a/auto-claude/spec/critique.py b/apps/backend/spec/critique.py
similarity index 100%
rename from auto-claude/spec/critique.py
rename to apps/backend/spec/critique.py
diff --git a/auto-claude/spec/discovery.py b/apps/backend/spec/discovery.py
similarity index 100%
rename from auto-claude/spec/discovery.py
rename to apps/backend/spec/discovery.py
diff --git a/auto-claude/spec/phases.py b/apps/backend/spec/phases.py
similarity index 100%
rename from auto-claude/spec/phases.py
rename to apps/backend/spec/phases.py
diff --git a/auto-claude/spec/phases/README.md b/apps/backend/spec/phases/README.md
similarity index 100%
rename from auto-claude/spec/phases/README.md
rename to apps/backend/spec/phases/README.md
diff --git a/auto-claude/spec/phases/__init__.py b/apps/backend/spec/phases/__init__.py
similarity index 100%
rename from auto-claude/spec/phases/__init__.py
rename to apps/backend/spec/phases/__init__.py
diff --git a/auto-claude/spec/phases/discovery_phases.py b/apps/backend/spec/phases/discovery_phases.py
similarity index 100%
rename from auto-claude/spec/phases/discovery_phases.py
rename to apps/backend/spec/phases/discovery_phases.py
diff --git a/auto-claude/spec/phases/executor.py b/apps/backend/spec/phases/executor.py
similarity index 100%
rename from auto-claude/spec/phases/executor.py
rename to apps/backend/spec/phases/executor.py
diff --git a/auto-claude/spec/phases/models.py b/apps/backend/spec/phases/models.py
similarity index 100%
rename from auto-claude/spec/phases/models.py
rename to apps/backend/spec/phases/models.py
diff --git a/auto-claude/spec/phases/planning_phases.py b/apps/backend/spec/phases/planning_phases.py
similarity index 100%
rename from auto-claude/spec/phases/planning_phases.py
rename to apps/backend/spec/phases/planning_phases.py
diff --git a/auto-claude/spec/phases/requirements_phases.py b/apps/backend/spec/phases/requirements_phases.py
similarity index 100%
rename from auto-claude/spec/phases/requirements_phases.py
rename to apps/backend/spec/phases/requirements_phases.py
diff --git a/auto-claude/spec/phases/spec_phases.py b/apps/backend/spec/phases/spec_phases.py
similarity index 100%
rename from auto-claude/spec/phases/spec_phases.py
rename to apps/backend/spec/phases/spec_phases.py
diff --git a/auto-claude/spec/phases/utils.py b/apps/backend/spec/phases/utils.py
similarity index 100%
rename from auto-claude/spec/phases/utils.py
rename to apps/backend/spec/phases/utils.py
diff --git a/auto-claude/spec/pipeline.py b/apps/backend/spec/pipeline.py
similarity index 100%
rename from auto-claude/spec/pipeline.py
rename to apps/backend/spec/pipeline.py
diff --git a/auto-claude/spec/pipeline/__init__.py b/apps/backend/spec/pipeline/__init__.py
similarity index 100%
rename from auto-claude/spec/pipeline/__init__.py
rename to apps/backend/spec/pipeline/__init__.py
diff --git a/auto-claude/spec/pipeline/agent_runner.py b/apps/backend/spec/pipeline/agent_runner.py
similarity index 100%
rename from auto-claude/spec/pipeline/agent_runner.py
rename to apps/backend/spec/pipeline/agent_runner.py
diff --git a/auto-claude/spec/pipeline/models.py b/apps/backend/spec/pipeline/models.py
similarity index 100%
rename from auto-claude/spec/pipeline/models.py
rename to apps/backend/spec/pipeline/models.py
diff --git a/auto-claude/spec/pipeline/orchestrator.py b/apps/backend/spec/pipeline/orchestrator.py
similarity index 100%
rename from auto-claude/spec/pipeline/orchestrator.py
rename to apps/backend/spec/pipeline/orchestrator.py
diff --git a/auto-claude/spec/requirements.py b/apps/backend/spec/requirements.py
similarity index 100%
rename from auto-claude/spec/requirements.py
rename to apps/backend/spec/requirements.py
diff --git a/auto-claude/spec/validate_pkg/README.md b/apps/backend/spec/validate_pkg/README.md
similarity index 100%
rename from auto-claude/spec/validate_pkg/README.md
rename to apps/backend/spec/validate_pkg/README.md
diff --git a/auto-claude/spec/validate_pkg/__init__.py b/apps/backend/spec/validate_pkg/__init__.py
similarity index 100%
rename from auto-claude/spec/validate_pkg/__init__.py
rename to apps/backend/spec/validate_pkg/__init__.py
diff --git a/auto-claude/spec/validate_pkg/auto_fix.py b/apps/backend/spec/validate_pkg/auto_fix.py
similarity index 100%
rename from auto-claude/spec/validate_pkg/auto_fix.py
rename to apps/backend/spec/validate_pkg/auto_fix.py
diff --git a/auto-claude/spec/validate_pkg/models.py b/apps/backend/spec/validate_pkg/models.py
similarity index 100%
rename from auto-claude/spec/validate_pkg/models.py
rename to apps/backend/spec/validate_pkg/models.py
diff --git a/auto-claude/spec/validate_pkg/schemas.py b/apps/backend/spec/validate_pkg/schemas.py
similarity index 100%
rename from auto-claude/spec/validate_pkg/schemas.py
rename to apps/backend/spec/validate_pkg/schemas.py
diff --git a/auto-claude/spec/validate_pkg/spec_validator.py b/apps/backend/spec/validate_pkg/spec_validator.py
similarity index 100%
rename from auto-claude/spec/validate_pkg/spec_validator.py
rename to apps/backend/spec/validate_pkg/spec_validator.py
diff --git a/auto-claude/spec/validate_pkg/validators/__init__.py b/apps/backend/spec/validate_pkg/validators/__init__.py
similarity index 100%
rename from auto-claude/spec/validate_pkg/validators/__init__.py
rename to apps/backend/spec/validate_pkg/validators/__init__.py
diff --git a/auto-claude/spec/validate_pkg/validators/context_validator.py b/apps/backend/spec/validate_pkg/validators/context_validator.py
similarity index 100%
rename from auto-claude/spec/validate_pkg/validators/context_validator.py
rename to apps/backend/spec/validate_pkg/validators/context_validator.py
diff --git a/auto-claude/spec/validate_pkg/validators/implementation_plan_validator.py b/apps/backend/spec/validate_pkg/validators/implementation_plan_validator.py
similarity index 100%
rename from auto-claude/spec/validate_pkg/validators/implementation_plan_validator.py
rename to apps/backend/spec/validate_pkg/validators/implementation_plan_validator.py
diff --git a/auto-claude/spec/validate_pkg/validators/prereqs_validator.py b/apps/backend/spec/validate_pkg/validators/prereqs_validator.py
similarity index 100%
rename from auto-claude/spec/validate_pkg/validators/prereqs_validator.py
rename to apps/backend/spec/validate_pkg/validators/prereqs_validator.py
diff --git a/auto-claude/spec/validate_pkg/validators/spec_document_validator.py b/apps/backend/spec/validate_pkg/validators/spec_document_validator.py
similarity index 100%
rename from auto-claude/spec/validate_pkg/validators/spec_document_validator.py
rename to apps/backend/spec/validate_pkg/validators/spec_document_validator.py
diff --git a/auto-claude/spec/validate_spec.py b/apps/backend/spec/validate_spec.py
similarity index 100%
rename from auto-claude/spec/validate_spec.py
rename to apps/backend/spec/validate_spec.py
diff --git a/auto-claude/spec/validation_strategy.py b/apps/backend/spec/validation_strategy.py
similarity index 100%
rename from auto-claude/spec/validation_strategy.py
rename to apps/backend/spec/validation_strategy.py
diff --git a/auto-claude/spec/validator.py b/apps/backend/spec/validator.py
similarity index 100%
rename from auto-claude/spec/validator.py
rename to apps/backend/spec/validator.py
diff --git a/auto-claude/spec/writer.py b/apps/backend/spec/writer.py
similarity index 100%
rename from auto-claude/spec/writer.py
rename to apps/backend/spec/writer.py
diff --git a/auto-claude/spec_contract.json b/apps/backend/spec_contract.json
similarity index 100%
rename from auto-claude/spec_contract.json
rename to apps/backend/spec_contract.json
diff --git a/auto-claude/task_logger/README.md b/apps/backend/task_logger/README.md
similarity index 100%
rename from auto-claude/task_logger/README.md
rename to apps/backend/task_logger/README.md
diff --git a/auto-claude/task_logger/__init__.py b/apps/backend/task_logger/__init__.py
similarity index 100%
rename from auto-claude/task_logger/__init__.py
rename to apps/backend/task_logger/__init__.py
diff --git a/auto-claude/task_logger/capture.py b/apps/backend/task_logger/capture.py
similarity index 100%
rename from auto-claude/task_logger/capture.py
rename to apps/backend/task_logger/capture.py
diff --git a/auto-claude/task_logger/logger.py b/apps/backend/task_logger/logger.py
similarity index 100%
rename from auto-claude/task_logger/logger.py
rename to apps/backend/task_logger/logger.py
diff --git a/auto-claude/task_logger/main.py b/apps/backend/task_logger/main.py
similarity index 100%
rename from auto-claude/task_logger/main.py
rename to apps/backend/task_logger/main.py
diff --git a/auto-claude/task_logger/models.py b/apps/backend/task_logger/models.py
similarity index 100%
rename from auto-claude/task_logger/models.py
rename to apps/backend/task_logger/models.py
diff --git a/auto-claude/task_logger/storage.py b/apps/backend/task_logger/storage.py
similarity index 100%
rename from auto-claude/task_logger/storage.py
rename to apps/backend/task_logger/storage.py
diff --git a/auto-claude/task_logger/streaming.py b/apps/backend/task_logger/streaming.py
similarity index 100%
rename from auto-claude/task_logger/streaming.py
rename to apps/backend/task_logger/streaming.py
diff --git a/auto-claude/task_logger/utils.py b/apps/backend/task_logger/utils.py
similarity index 100%
rename from auto-claude/task_logger/utils.py
rename to apps/backend/task_logger/utils.py
diff --git a/auto-claude/test_discovery.py b/apps/backend/test_discovery.py
similarity index 100%
rename from auto-claude/test_discovery.py
rename to apps/backend/test_discovery.py
diff --git a/auto-claude/ui/__init__.py b/apps/backend/ui/__init__.py
similarity index 100%
rename from auto-claude/ui/__init__.py
rename to apps/backend/ui/__init__.py
diff --git a/auto-claude/ui/boxes.py b/apps/backend/ui/boxes.py
similarity index 100%
rename from auto-claude/ui/boxes.py
rename to apps/backend/ui/boxes.py
diff --git a/auto-claude/ui/capabilities.py b/apps/backend/ui/capabilities.py
similarity index 100%
rename from auto-claude/ui/capabilities.py
rename to apps/backend/ui/capabilities.py
diff --git a/auto-claude/ui/colors.py b/apps/backend/ui/colors.py
similarity index 100%
rename from auto-claude/ui/colors.py
rename to apps/backend/ui/colors.py
diff --git a/auto-claude/ui/formatters.py b/apps/backend/ui/formatters.py
similarity index 100%
rename from auto-claude/ui/formatters.py
rename to apps/backend/ui/formatters.py
diff --git a/auto-claude/ui/icons.py b/apps/backend/ui/icons.py
similarity index 100%
rename from auto-claude/ui/icons.py
rename to apps/backend/ui/icons.py
diff --git a/auto-claude/ui/main.py b/apps/backend/ui/main.py
similarity index 100%
rename from auto-claude/ui/main.py
rename to apps/backend/ui/main.py
diff --git a/auto-claude/ui/menu.py b/apps/backend/ui/menu.py
similarity index 100%
rename from auto-claude/ui/menu.py
rename to apps/backend/ui/menu.py
diff --git a/auto-claude/ui/progress.py b/apps/backend/ui/progress.py
similarity index 100%
rename from auto-claude/ui/progress.py
rename to apps/backend/ui/progress.py
diff --git a/auto-claude/ui/spinner.py b/apps/backend/ui/spinner.py
similarity index 100%
rename from auto-claude/ui/spinner.py
rename to apps/backend/ui/spinner.py
diff --git a/auto-claude/ui/status.py b/apps/backend/ui/status.py
similarity index 100%
rename from auto-claude/ui/status.py
rename to apps/backend/ui/status.py
diff --git a/auto-claude/ui/statusline.py b/apps/backend/ui/statusline.py
similarity index 100%
rename from auto-claude/ui/statusline.py
rename to apps/backend/ui/statusline.py
diff --git a/auto-claude/validation_strategy.py b/apps/backend/validation_strategy.py
similarity index 100%
rename from auto-claude/validation_strategy.py
rename to apps/backend/validation_strategy.py
diff --git a/apps/backend/workspace.py b/apps/backend/workspace.py
new file mode 100644
index 00000000..7aec54d2
--- /dev/null
+++ b/apps/backend/workspace.py
@@ -0,0 +1,72 @@
+"""
+Workspace management module facade.
+
+Provides workspace setup and management utilities for isolated builds.
+Re-exports from core.workspace for clean imports.
+"""
+
+from core.workspace import (
+ MergeLock,
+ MergeLockError,
+ ParallelMergeResult,
+ ParallelMergeTask,
+ WorkspaceChoice,
+ WorkspaceMode,
+ check_existing_build,
+ choose_workspace,
+ cleanup_all_worktrees,
+ copy_spec_to_worktree,
+ create_conflict_file_with_git,
+ discard_existing_build,
+ finalize_workspace,
+ get_changed_files_from_branch,
+ get_current_branch,
+ get_existing_build_worktree,
+ get_file_content_from_ref,
+ handle_workspace_choice,
+ has_uncommitted_changes,
+ is_binary_file,
+ is_process_running,
+ list_all_worktrees,
+ merge_existing_build,
+ print_conflict_info,
+ print_merge_success,
+ review_existing_build,
+ setup_workspace,
+ show_build_summary,
+ show_changed_files,
+ validate_merged_syntax,
+)
+
+__all__ = [
+ "MergeLock",
+ "MergeLockError",
+ "ParallelMergeResult",
+ "ParallelMergeTask",
+ "WorkspaceChoice",
+ "WorkspaceMode",
+ "check_existing_build",
+ "choose_workspace",
+ "cleanup_all_worktrees",
+ "copy_spec_to_worktree",
+ "create_conflict_file_with_git",
+ "discard_existing_build",
+ "finalize_workspace",
+ "get_changed_files_from_branch",
+ "get_current_branch",
+ "get_existing_build_worktree",
+ "get_file_content_from_ref",
+ "handle_workspace_choice",
+ "has_uncommitted_changes",
+ "is_binary_file",
+ "is_process_running",
+ "list_all_worktrees",
+ "merge_existing_build",
+ "print_conflict_info",
+ "print_merge_success",
+ "review_existing_build",
+ "setup_workspace",
+ "show_build_summary",
+ "show_changed_files",
+ "validate_merged_syntax",
+]
diff --git a/auto-claude/worktree.py b/apps/backend/worktree.py
similarity index 77%
rename from auto-claude/worktree.py
rename to apps/backend/worktree.py
index d8a030a1..bbd95476 100644
--- a/auto-claude/worktree.py
+++ b/apps/backend/worktree.py
@@ -19,20 +19,20 @@ import sys
from pathlib import Path
from types import ModuleType
-# Ensure auto-claude is in sys.path
-_auto_claude_dir = Path(__file__).parent
-if str(_auto_claude_dir) not in sys.path:
- sys.path.insert(0, str(_auto_claude_dir))
+# Ensure apps/backend is in sys.path
+_backend_dir = Path(__file__).parent
+if str(_backend_dir) not in sys.path:
+ sys.path.insert(0, str(_backend_dir))
# Create a minimal 'core' module if it doesn't exist (to avoid importing core/__init__.py)
if "core" not in sys.modules:
_core_module = ModuleType("core")
- _core_module.__file__ = str(_auto_claude_dir / "core" / "__init__.py")
- _core_module.__path__ = [str(_auto_claude_dir / "core")]
+ _core_module.__file__ = str(_backend_dir / "core" / "__init__.py")
+ _core_module.__path__ = [str(_backend_dir / "core")]
sys.modules["core"] = _core_module
# Now load core.worktree directly
-_worktree_file = _auto_claude_dir / "core" / "worktree.py"
+_worktree_file = _backend_dir / "core" / "worktree.py"
_spec = importlib.util.spec_from_file_location("core.worktree", _worktree_file)
_worktree_module = importlib.util.module_from_spec(_spec)
sys.modules["core.worktree"] = _worktree_module
diff --git a/auto-claude-ui/.env.example b/apps/frontend/.env.example
similarity index 100%
rename from auto-claude-ui/.env.example
rename to apps/frontend/.env.example
diff --git a/auto-claude-ui/.gitignore b/apps/frontend/.gitignore
similarity index 73%
rename from auto-claude-ui/.gitignore
rename to apps/frontend/.gitignore
index 52160aaa..e9729119 100644
--- a/auto-claude-ui/.gitignore
+++ b/apps/frontend/.gitignore
@@ -45,7 +45,15 @@ coverage/
*.temp
.cache/
-# Package manager locks (keep one)
-# package-lock.json
-# yarn.lock
-# pnpm-lock.yaml
+# Package manager locks - using npm only
+yarn.lock
+pnpm-lock.yaml
+bun.lock
+bun.lockb
+
+# Backup files
+*.backup
+
+# Test files in root
+test-*.js
+test-*.cjs
diff --git a/apps/frontend/.husky/pre-commit b/apps/frontend/.husky/pre-commit
new file mode 100644
index 00000000..b10ebb83
--- /dev/null
+++ b/apps/frontend/.husky/pre-commit
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+echo "Running pre-commit checks..."
+
+# Run lint-staged (handles staged .ts/.tsx files)
+npm exec lint-staged
+
+# Run TypeScript type check
+echo "Running type check..."
+npm run typecheck
+if [ $? -ne 0 ]; then
+ echo "Type check failed. Please fix TypeScript errors before committing."
+ exit 1
+fi
+
+# Run linting
+echo "Running lint..."
+npm run lint
+if [ $? -ne 0 ]; then
+ echo "Lint failed. Run 'npm run lint:fix' to auto-fix issues."
+ exit 1
+fi
+
+# Check for vulnerabilities
+echo "Checking for vulnerabilities..."
+npm audit --audit-level=high
+if [ $? -ne 0 ]; then
+ echo "Security vulnerabilities found. Run 'npm audit fix' to resolve."
+ exit 1
+fi
+
+echo "All pre-commit checks passed!"
diff --git a/apps/frontend/CONTRIBUTING.md b/apps/frontend/CONTRIBUTING.md
new file mode 100644
index 00000000..30bf164a
--- /dev/null
+++ b/apps/frontend/CONTRIBUTING.md
@@ -0,0 +1,166 @@
+# Contributing to Auto Claude UI
+
+Thank you for your interest in contributing! This document provides guidelines for contributing to the frontend application.
+
+## Prerequisites
+
+- **Node.js v24.12.0 LTS** - Download from https://nodejs.org
+- **npm v10+** - Included with Node.js
+- **Git** - For version control
+
+## Getting Started
+
+```bash
+# Clone the repository
+git clone https://github.com/AndyMik90/Auto-Claude.git
+cd Auto-Claude/apps/frontend
+
+# Install dependencies
+npm install
+
+# Start development server
+npm run dev
+```
+
+## Code Style
+
+### Architecture Principles
+
+1. **Feature-based Organization**: Group related code in feature folders
+2. **Single Responsibility**: Each file does one thing well
+3. **DRY**: Extract common patterns into shared modules
+4. **KISS**: Simple solutions over complex ones
+5. **SOLID**: Follow object-oriented design principles
+
+### Feature Module Structure
+
+Each feature follows this structure:
+
+```
+features/[feature-name]/
+├── components/ # Feature-specific React components
+├── hooks/ # Feature-specific hooks
+├── store/ # Zustand store
+└── index.ts # Public API exports
+```
+
+### File Naming
+
+| Type | Convention | Example |
+|------|------------|---------|
+| React Components | PascalCase | `TaskCard.tsx` |
+| Hooks | camelCase with `use` | `useTaskStore.ts` |
+| Stores | kebab-case | `task-store.ts` |
+| Types | PascalCase | `Task.ts` |
+| Constants | SCREAMING_SNAKE_CASE | `MAX_RETRIES` |
+
+### Import Order
+
+```typescript
+// 1. External libraries
+import { useState } from 'react';
+import { Settings2 } from 'lucide-react';
+
+// 2. Shared components and utilities
+import { Button } from '@components/button';
+import { cn } from '@lib/utils';
+
+// 3. Feature imports
+import { useTaskStore } from '../store/task-store';
+
+// 4. Types (use 'import type')
+import type { Task } from '@shared/types';
+```
+
+### TypeScript Guidelines
+
+- **No implicit `any`**: Always type parameters and variables
+- **Use `type` for objects**: Prefer `type` over `interface`
+- **Export types separately**: Use `export type` for type-only exports
+
+```typescript
+// Good
+type TaskStatus = 'backlog' | 'in_progress' | 'done';
+
+interface TaskCardProps {
+ task: Task;
+ onClick: () => void;
+}
+
+// Bad
+function processTask(data: any) { ... }
+```
+
+## Testing
+
+```bash
+# Run unit tests
+npm test
+
+# Watch mode
+npm run test:watch
+
+# Coverage report
+npm run test:coverage
+
+# E2E tests
+npm run test:e2e
+```
+
+### Writing Tests
+
+```typescript
+import { describe, it, expect, vi } from 'vitest';
+import { render, screen } from '@testing-library/react';
+import { TaskCard } from './TaskCard';
+
+describe('TaskCard', () => {
+ it('renders task title', () => {
+ const task = { id: '1', title: 'Test Task' };
+ render();
+
+ expect(screen.getByText('Test Task')).toBeInTheDocument();
+ });
+});
+```
+
+## Before Submitting
+
+1. **Run linting**:
+ ```bash
+ npm run lint:fix
+ ```
+
+2. **Check types**:
+ ```bash
+ npm run typecheck
+ ```
+
+3. **Run tests**:
+ ```bash
+ npm test
+ ```
+
+4. **Test the build**:
+ ```bash
+ npm run build
+ ```
+
+## Pull Request Process
+
+1. Create a feature branch: `git checkout -b feature/my-feature`
+2. Make your changes following the guidelines above
+3. Commit with clear messages
+4. Push and create a Pull Request
+5. Address review feedback
+
+## Security
+
+- Never commit secrets, API keys, or tokens
+- Use environment variables for sensitive data
+- Validate all IPC data
+- Use contextBridge for renderer-main communication
+
+## Questions?
+
+Open an issue or reach out to the maintainers.
diff --git a/apps/frontend/README.md b/apps/frontend/README.md
new file mode 100644
index 00000000..67812918
--- /dev/null
+++ b/apps/frontend/README.md
@@ -0,0 +1,221 @@
+# Auto Claude UI - Frontend
+
+A modern Electron + React desktop application for the Auto Claude autonomous coding framework.
+
+## Prerequisites
+
+### Node.js v24.12.0 LTS (Required)
+
+This project requires **Node.js v24.12.0 LTS** (Latest LTS version as of December 2024).
+
+**Download:** https://nodejs.org/en/download/
+
+> **IMPORTANT:** When installing Node.js on Windows, make sure to check:
+> - "Add to PATH"
+> - "npm package manager"
+
+**Verify installation:**
+```bash
+node --version # Should output: v24.12.0
+npm --version # Should output: 11.x.x or higher
+```
+
+> **Note:** npm is included with Node.js. If `npm` is not found after installing Node.js, you need to reinstall Node.js properly.
+
+## Quick Start
+
+```bash
+# Navigate to frontend directory
+cd apps/frontend
+
+# Install dependencies (includes native module rebuild)
+npm install
+
+# Start development server
+npm run dev
+```
+
+## Security
+
+This project maintains **0 vulnerabilities**. Run `npm audit` to verify.
+
+```bash
+npm audit
+# Expected output: found 0 vulnerabilities
+```
+
+## Architecture
+
+This project follows a **feature-based architecture** for better maintainability and scalability.
+
+```
+src/
+├── main/ # Electron main process
+│ ├── agent/ # Agent management
+│ ├── changelog/ # Changelog generation
+│ ├── claude-profile/ # Claude profile management
+│ ├── insights/ # Code analysis
+│ ├── ipc-handlers/ # IPC communication handlers
+│ ├── terminal/ # PTY and terminal management
+│ └── updater/ # App update service
+│
+├── preload/ # Electron preload scripts
+│ └── api/ # IPC API modules
+│
+├── renderer/ # React frontend
+│ ├── features/ # Feature modules (self-contained)
+│ │ ├── tasks/ # Task management, kanban, creation
+│ │ ├── terminals/ # Terminal emulation
+│ │ ├── projects/ # Project management, file explorer
+│ │ ├── settings/ # App and project settings
+│ │ ├── roadmap/ # Roadmap generation
+│ │ ├── ideation/ # AI-powered brainstorming
+│ │ ├── insights/ # Code analysis
+│ │ ├── changelog/ # Release management
+│ │ ├── github/ # GitHub integration
+│ │ ├── agents/ # Claude profile management
+│ │ ├── worktrees/ # Git worktree management
+│ │ └── onboarding/ # First-time setup wizard
+│ │
+│ ├── shared/ # Shared resources
+│ │ ├── components/ # Reusable UI components
+│ │ ├── hooks/ # Shared React hooks
+│ │ └── lib/ # Utilities and helpers
+│ │
+│ └── hooks/ # App-level hooks
+│
+└── shared/ # Shared between main/renderer
+ ├── types/ # TypeScript type definitions
+ ├── constants/ # Application constants
+ └── utils/ # Shared utilities
+```
+
+## Scripts
+
+| Command | Description |
+|---------|-------------|
+| `npm run dev` | Start development server with hot reload |
+| `npm run build` | Build for production |
+| `npm run package` | Build and package for current platform |
+| `npm run package:win` | Package for Windows |
+| `npm run package:mac` | Package for macOS |
+| `npm run package:linux` | Package for Linux |
+| `npm test` | Run unit tests |
+| `npm run test:watch` | Run tests in watch mode |
+| `npm run test:coverage` | Run tests with coverage |
+| `npm run lint` | Check for lint errors |
+| `npm run lint:fix` | Auto-fix lint errors |
+| `npm run typecheck` | Type check TypeScript |
+| `npm audit` | Check for security vulnerabilities |
+
+## Development Guidelines
+
+### Code Organization Principles
+
+1. **Feature-based Architecture**: Group related code by feature, not by type
+2. **Single Responsibility**: Each component/hook/store does one thing well
+3. **DRY (Don't Repeat Yourself)**: Extract reusable logic into shared modules
+4. **KISS (Keep It Simple)**: Prefer simple solutions over complex ones
+5. **SOLID Principles**: Apply object-oriented design principles
+
+### Naming Conventions
+
+| Type | Convention | Example |
+|------|------------|---------|
+| Components | PascalCase | `TaskCard.tsx` |
+| Hooks | camelCase with `use` prefix | `useTaskStore.ts` |
+| Stores | kebab-case with `-store` suffix | `task-store.ts` |
+| Types | PascalCase | `Task`, `TaskStatus` |
+| Constants | SCREAMING_SNAKE_CASE | `MAX_RETRIES` |
+
+### TypeScript Guidelines
+
+- **No implicit `any`**: Always type your variables and parameters
+- **Use `type` for simple objects**: Prefer `type` over `interface`
+- **Export types separately**: Use `export type` for type-only exports
+
+### Security Guidelines
+
+- **Never expose secrets**: API keys, tokens should stay in main process
+- **Validate IPC data**: Always validate data coming through IPC
+- **Use contextBridge**: Never expose Node.js APIs directly to renderer
+
+## Troubleshooting
+
+### npm not found
+
+If `npm` command is not recognized after installing Node.js:
+
+1. **Windows**: Reinstall Node.js from https://nodejs.org and ensure you check "Add to PATH"
+2. **macOS/Linux**: Add to your shell profile:
+ ```bash
+ export PATH="/usr/local/bin:$PATH"
+ ```
+3. Restart your terminal
+
+### Native module errors
+
+If you get errors about native modules (node-pty, etc.):
+
+```bash
+npm run rebuild
+```
+
+### Windows build tools required
+
+If electron-rebuild fails on Windows, install Visual Studio Build Tools:
+
+1. Download from https://visualstudio.microsoft.com/visual-cpp-build-tools/
+2. Select "Desktop development with C++" workload
+3. Restart terminal and run `npm install` again
+
+## Git Hooks
+
+This project uses Husky for Git hooks that run automatically:
+
+### Pre-commit Hook
+
+Runs before each commit:
+- **lint-staged**: Lints staged `.ts`/`.tsx` files
+- **typecheck**: TypeScript type checking
+- **lint**: ESLint checks
+- **npm audit**: Security vulnerability check (high severity)
+
+### Commit Message Format
+
+We use [Conventional Commits](https://www.conventionalcommits.org/). Your commit messages must follow this format:
+
+```
+type(scope): description
+```
+
+**Valid types:**
+| Type | Description |
+|------|-------------|
+| `feat` | A new feature |
+| `fix` | A bug fix |
+| `docs` | Documentation changes |
+| `style` | Code style (formatting, semicolons, etc.) |
+| `refactor` | Code refactoring (no feature/fix) |
+| `perf` | Performance improvements |
+| `test` | Adding or updating tests |
+| `build` | Build system or dependencies |
+| `ci` | CI/CD configuration |
+| `chore` | Maintenance tasks |
+| `revert` | Reverting a previous commit |
+
+**Examples:**
+```bash
+git commit -m "feat(tasks): add drag and drop support"
+git commit -m "fix(terminal): resolve scroll position issue"
+git commit -m "docs: update README with setup instructions"
+git commit -m "chore: update dependencies"
+```
+
+## Package Manager
+
+This project uses **npm** (not pnpm or yarn). The lock files for other package managers are ignored.
+
+## License
+
+AGPL-3.0
diff --git a/auto-claude-ui/design.json b/apps/frontend/design.json
similarity index 100%
rename from auto-claude-ui/design.json
rename to apps/frontend/design.json
diff --git a/auto-claude-ui/e2e/electron-helper.ts b/apps/frontend/e2e/electron-helper.ts
similarity index 100%
rename from auto-claude-ui/e2e/electron-helper.ts
rename to apps/frontend/e2e/electron-helper.ts
diff --git a/auto-claude-ui/e2e/flows.e2e.ts b/apps/frontend/e2e/flows.e2e.ts
similarity index 100%
rename from auto-claude-ui/e2e/flows.e2e.ts
rename to apps/frontend/e2e/flows.e2e.ts
diff --git a/auto-claude-ui/e2e/playwright.config.ts b/apps/frontend/e2e/playwright.config.ts
similarity index 100%
rename from auto-claude-ui/e2e/playwright.config.ts
rename to apps/frontend/e2e/playwright.config.ts
diff --git a/auto-claude-ui/electron.vite.config.ts b/apps/frontend/electron.vite.config.ts
similarity index 84%
rename from auto-claude-ui/electron.vite.config.ts
rename to apps/frontend/electron.vite.config.ts
index 846638fc..5dcaaf9f 100644
--- a/auto-claude-ui/electron.vite.config.ts
+++ b/apps/frontend/electron.vite.config.ts
@@ -47,7 +47,11 @@ export default defineConfig({
resolve: {
alias: {
'@': resolve(__dirname, 'src/renderer'),
- '@shared': resolve(__dirname, 'src/shared')
+ '@shared': resolve(__dirname, 'src/shared'),
+ '@features': resolve(__dirname, 'src/renderer/features'),
+ '@components': resolve(__dirname, 'src/renderer/shared/components'),
+ '@hooks': resolve(__dirname, 'src/renderer/shared/hooks'),
+ '@lib': resolve(__dirname, 'src/renderer/shared/lib')
}
},
server: {
diff --git a/auto-claude-ui/eslint.config.mjs b/apps/frontend/eslint.config.mjs
similarity index 82%
rename from auto-claude-ui/eslint.config.mjs
rename to apps/frontend/eslint.config.mjs
index d90ae77f..908d7123 100644
--- a/auto-claude-ui/eslint.config.mjs
+++ b/apps/frontend/eslint.config.mjs
@@ -74,6 +74,24 @@ export default tseslint.config(
}
},
{
- ignores: ['out/**', 'dist/**', '.eslintrc.cjs', 'eslint.config.mjs', 'node_modules/**']
+ files: ['**/*.cjs'],
+ languageOptions: {
+ globals: {
+ ...globals.node,
+ module: 'readonly',
+ require: 'readonly',
+ __dirname: 'readonly',
+ process: 'readonly',
+ console: 'readonly'
+ },
+ sourceType: 'commonjs'
+ },
+ rules: {
+ '@typescript-eslint/no-require-imports': 'off',
+ 'no-undef': 'off'
+ }
+ },
+ {
+ ignores: ['out/**', 'dist/**', '.eslintrc.cjs', 'eslint.config.mjs', 'node_modules/**', '**/*.cjs']
}
);
diff --git a/auto-claude-ui/package-lock.json b/apps/frontend/package-lock.json
similarity index 98%
rename from auto-claude-ui/package-lock.json
rename to apps/frontend/package-lock.json
index 422a26cc..b3896dad 100644
--- a/auto-claude-ui/package-lock.json
+++ b/apps/frontend/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "auto-claude-ui",
- "version": "2.6.5",
+ "version": "2.8.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "auto-claude-ui",
- "version": "2.6.5",
+ "version": "2.8.0",
"hasInstallScript": true,
"license": "AGPL-3.0",
"dependencies": {
@@ -40,7 +40,6 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"electron-updater": "^6.6.2",
- "kuzu": "^0.8.2",
"lucide-react": "^0.560.0",
"motion": "^12.23.26",
"react": "^19.2.3",
@@ -82,6 +81,10 @@
"typescript-eslint": "^8.49.0",
"vite": "^7.2.7",
"vitest": "^4.0.15"
+ },
+ "engines": {
+ "node": ">=24.0.0",
+ "npm": ">=10.0.0"
}
},
"node_modules/@alloc/quick-lru": {
@@ -149,6 +152,7 @@
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
@@ -534,6 +538,7 @@
}
],
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=18"
},
@@ -557,6 +562,7 @@
}
],
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=18"
}
@@ -596,6 +602,7 @@
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@dnd-kit/accessibility": "^3.1.1",
"@dnd-kit/utilities": "^3.2.2",
@@ -990,7 +997,6 @@
"dev": true,
"license": "BSD-2-Clause",
"optional": true,
- "peer": true,
"dependencies": {
"cross-dirname": "^0.1.0",
"debug": "^4.3.4",
@@ -1012,7 +1018,6 @@
"dev": true,
"license": "MIT",
"optional": true,
- "peer": true,
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
@@ -4013,8 +4018,7 @@
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
@@ -4201,6 +4205,7 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
"integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"csstype": "^3.2.2"
}
@@ -4211,6 +4216,7 @@
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
"devOptional": true,
"license": "MIT",
+ "peer": true,
"peerDependencies": {
"@types/react": "^19.2.0"
}
@@ -4302,6 +4308,7 @@
"integrity": "sha512-N9lBGA9o9aqb1hVMc9hzySbhKibHmB+N3IpoShyV6HyQYRGIhlrO5rQgttypi+yEeKsKI4idxC8Jw6gXKD4THA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.49.0",
"@typescript-eslint/types": "8.49.0",
@@ -4701,7 +4708,8 @@
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/7zip-bin": {
"version": "5.2.0",
@@ -4723,6 +4731,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -4783,6 +4792,7 @@
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -4824,6 +4834,7 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -4833,6 +4844,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
@@ -4929,26 +4941,6 @@
"node": ">=12.13.0"
}
},
- "node_modules/aproba": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz",
- "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==",
- "license": "ISC"
- },
- "node_modules/are-we-there-yet": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
- "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "dependencies": {
- "delegates": "^1.0.0",
- "readable-stream": "^3.6.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -4973,7 +4965,6 @@
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
"dev": true,
"license": "Apache-2.0",
- "peer": true,
"dependencies": {
"dequal": "^2.0.3"
}
@@ -5179,6 +5170,7 @@
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true,
"license": "MIT"
},
"node_modules/at-least-node": {
@@ -5244,17 +5236,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/axios": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
- "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
- "license": "MIT",
- "dependencies": {
- "follow-redirects": "^1.15.6",
- "form-data": "^4.0.4",
- "proxy-from-env": "^1.1.0"
- }
- },
"node_modules/bail": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
@@ -5368,6 +5349,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@@ -5565,6 +5547,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -5718,6 +5701,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true,
"license": "ISC",
"engines": {
"node": ">=10"
@@ -5816,6 +5800,7 @@
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
"license": "ISC",
"dependencies": {
"string-width": "^4.2.0",
@@ -5858,50 +5843,11 @@
"node": ">=6"
}
},
- "node_modules/cmake-js": {
- "version": "7.4.0",
- "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-7.4.0.tgz",
- "integrity": "sha512-Lw0JxEHrmk+qNj1n9W9d4IvkDdYTBn7l2BW6XmtLj7WPpIo2shvxUy+YokfjMxAAOELNonQwX3stkPhM5xSC2Q==",
- "license": "MIT",
- "dependencies": {
- "axios": "^1.6.5",
- "debug": "^4",
- "fs-extra": "^11.2.0",
- "memory-stream": "^1.0.0",
- "node-api-headers": "^1.1.0",
- "npmlog": "^6.0.2",
- "rc": "^1.2.7",
- "semver": "^7.5.4",
- "tar": "^6.2.0",
- "url-join": "^4.0.1",
- "which": "^2.0.2",
- "yargs": "^17.7.2"
- },
- "bin": {
- "cmake-js": "bin/cmake-js"
- },
- "engines": {
- "node": ">= 14.15.0"
- }
- },
- "node_modules/cmake-js/node_modules/fs-extra": {
- "version": "11.3.3",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz",
- "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=14.14"
- }
- },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
@@ -5914,17 +5860,9 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
"license": "MIT"
},
- "node_modules/color-support": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
- "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
- "license": "ISC",
- "bin": {
- "color-support": "bin.js"
- }
- },
"node_modules/colorette": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
@@ -5936,6 +5874,7 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
@@ -6049,12 +5988,6 @@
"node": ">=16 || 14 >=14.17"
}
},
- "node_modules/console-control-strings": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
- "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
- "license": "ISC"
- },
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@@ -6087,8 +6020,7 @@
"integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==",
"dev": true,
"license": "MIT",
- "optional": true,
- "peer": true
+ "optional": true
},
"node_modules/cross-spawn": {
"version": "7.0.6",
@@ -6271,15 +6203,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "license": "MIT",
- "engines": {
- "node": ">=4.0.0"
- }
- },
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -6350,17 +6273,12 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
- "node_modules/delegates": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
- "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
- "license": "MIT"
- },
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@@ -6437,6 +6355,7 @@
"integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"app-builder-lib": "26.0.12",
"builder-util": "26.0.11",
@@ -6494,8 +6413,7 @@
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/dotenv": {
"version": "16.6.1",
@@ -6530,6 +6448,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
@@ -6570,6 +6489,7 @@
"dev": true,
"hasInstallScript": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@electron/get": "^2.0.0",
"@types/node": "^22.7.7",
@@ -6698,7 +6618,6 @@
"dev": true,
"hasInstallScript": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@electron/asar": "^3.2.1",
"debug": "^4.1.1",
@@ -6719,7 +6638,6 @@
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"graceful-fs": "^4.1.2",
"jsonfile": "^4.0.0",
@@ -6735,7 +6653,6 @@
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"dev": true,
"license": "MIT",
- "peer": true,
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
@@ -6746,7 +6663,6 @@
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">= 4.0.0"
}
@@ -6772,6 +6688,7 @@
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
"license": "MIT"
},
"node_modules/encoding": {
@@ -6925,6 +6842,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -6934,6 +6852,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -6978,6 +6897,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
@@ -6990,6 +6910,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -7086,6 +7007,7 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -7110,6 +7032,7 @@
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -7575,26 +7498,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/follow-redirects": {
- "version": "1.15.11",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
- "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/RubenVerborgh"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=4.0"
- },
- "peerDependenciesMeta": {
- "debug": {
- "optional": true
- }
- }
- },
"node_modules/for-each": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
@@ -7645,6 +7548,7 @@
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
@@ -7716,6 +7620,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dev": true,
"license": "ISC",
"dependencies": {
"minipass": "^3.0.0"
@@ -7750,6 +7655,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -7786,26 +7692,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/gauge": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
- "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "dependencies": {
- "aproba": "^1.0.3 || ^2.0.0",
- "color-support": "^1.1.3",
- "console-control-strings": "^1.1.0",
- "has-unicode": "^2.0.1",
- "signal-exit": "^3.0.7",
- "string-width": "^4.2.3",
- "strip-ansi": "^6.0.1",
- "wide-align": "^1.1.5"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
"node_modules/generator-function": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
@@ -7830,6 +7716,7 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
"license": "ISC",
"engines": {
"node": "6.* || 8.* || >= 10.*"
@@ -7852,6 +7739,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
@@ -7885,6 +7773,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
@@ -8038,6 +7927,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -8134,6 +8024,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -8146,6 +8037,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
@@ -8157,16 +8049,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/has-unicode": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
- "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
- "license": "ISC"
- },
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@@ -8485,12 +8372,7 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "license": "ISC"
- },
- "node_modules/ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true,
"license": "ISC"
},
"node_modules/inline-style-parser": {
@@ -8736,6 +8618,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -9055,6 +8938,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
"license": "ISC"
},
"node_modules/iterator.prototype": {
@@ -9144,6 +9028,7 @@
"integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"cssstyle": "^4.2.1",
"data-urls": "^5.0.0",
@@ -9271,24 +9156,6 @@
"json-buffer": "3.0.1"
}
},
- "node_modules/kuzu": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/kuzu/-/kuzu-0.8.2.tgz",
- "integrity": "sha512-GdaDfutKf/MXZQYZwhpupnUJLODbLheplzNUWy0CgU4HW/Yk8AYij7K4/FP8G/zlNNvn8pNP/jj19bg0vCwcYw==",
- "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "cmake-js": "^7.3.0",
- "node-addon-api": "^6.0.0"
- }
- },
- "node_modules/kuzu/node_modules/node-addon-api": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz",
- "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==",
- "license": "MIT"
- },
"node_modules/lazy-val": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz",
@@ -10093,7 +9960,6 @@
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"lz-string": "bin/bin.js"
}
@@ -10216,6 +10082,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -10503,15 +10370,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/memory-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/memory-stream/-/memory-stream-1.0.0.tgz",
- "integrity": "sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww==",
- "license": "MIT",
- "dependencies": {
- "readable-stream": "^3.4.0"
- }
- },
"node_modules/micromark": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
@@ -11119,6 +10977,7 @@
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -11128,6 +10987,7 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
@@ -11189,6 +11049,7 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -11198,6 +11059,7 @@
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
@@ -11280,12 +11142,14 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true,
"license": "ISC"
},
"node_modules/minizlib": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"minipass": "^3.0.0",
@@ -11299,12 +11163,14 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true,
"license": "ISC"
},
"node_modules/mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true,
"license": "MIT",
"bin": {
"mkdirp": "bin/cmd.js"
@@ -11430,12 +11296,6 @@
"license": "MIT",
"optional": true
},
- "node_modules/node-api-headers": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/node-api-headers/-/node-api-headers-1.7.0.tgz",
- "integrity": "sha512-uJMGdkhVwu9+I3UsVvI3KW6ICAy/yDfsu5Br9rSnTtY3WpoaComXvKloiV5wtx0Md2rn0B9n29Ys2WMNwWxj9A==",
- "license": "MIT"
- },
"node_modules/node-api-version": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.1.tgz",
@@ -11482,22 +11342,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/npmlog": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
- "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "dependencies": {
- "are-we-there-yet": "^3.0.0",
- "console-control-strings": "^1.1.0",
- "gauge": "^4.0.3",
- "set-blocking": "^2.0.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
"node_modules/nwsapi": {
"version": "2.2.23",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz",
@@ -11939,6 +11783,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=12"
},
@@ -12036,6 +11881,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -12072,7 +11918,6 @@
"dev": true,
"license": "MIT",
"optional": true,
- "peer": true,
"dependencies": {
"commander": "^9.4.0"
},
@@ -12090,7 +11935,6 @@
"dev": true,
"license": "MIT",
"optional": true,
- "peer": true,
"engines": {
"node": "^12.20.0 || >=14"
}
@@ -12111,7 +11955,6 @@
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"ansi-regex": "^5.0.1",
"ansi-styles": "^5.0.0",
@@ -12127,7 +11970,6 @@
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -12140,8 +11982,7 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/proc-log": {
"version": "2.0.1",
@@ -12206,12 +12047,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/proxy-from-env": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
- "license": "MIT"
- },
"node_modules/pump": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
@@ -12246,35 +12081,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "bin": {
- "rc": "cli.js"
- }
- },
- "node_modules/rc/node_modules/strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/react": {
"version": "19.2.3",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -12284,6 +12096,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@@ -12431,6 +12244,7 @@
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
@@ -12568,6 +12382,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -12814,6 +12629,7 @@
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
"funding": [
{
"type": "github",
@@ -12944,12 +12760,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
- "license": "ISC"
- },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -13109,6 +12919,7 @@
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
"license": "ISC"
},
"node_modules/simple-update-notifier": {
@@ -13298,6 +13109,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.2.0"
@@ -13317,6 +13129,7 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
@@ -13459,6 +13272,7 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
@@ -13572,7 +13386,8 @@
"version": "4.1.18",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/tapable": {
"version": "2.3.0",
@@ -13592,6 +13407,7 @@
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
+ "dev": true,
"license": "ISC",
"dependencies": {
"chownr": "^2.0.0",
@@ -13609,6 +13425,7 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "dev": true,
"license": "ISC",
"engines": {
"node": ">=8"
@@ -13618,6 +13435,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true,
"license": "ISC"
},
"node_modules/temp": {
@@ -13626,7 +13444,6 @@
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"mkdirp": "^0.5.1",
"rimraf": "~2.6.2"
@@ -13653,7 +13470,6 @@
"deprecated": "Glob versions prior to v9 are no longer supported",
"dev": true,
"license": "ISC",
- "peer": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -13675,7 +13491,6 @@
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"license": "ISC",
- "peer": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -13689,7 +13504,6 @@
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"minimist": "^1.2.6"
},
@@ -13704,7 +13518,6 @@
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dev": true,
"license": "ISC",
- "peer": true,
"dependencies": {
"glob": "^7.1.3"
},
@@ -14021,6 +13834,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -14242,12 +14056,6 @@
"punycode": "^2.1.0"
}
},
- "node_modules/url-join": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
- "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
- "license": "MIT"
- },
"node_modules/use-callback-ref": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
@@ -14367,6 +14175,7 @@
"integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@@ -15087,6 +14896,7 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
@@ -15204,15 +15014,6 @@
"node": ">=8"
}
},
- "node_modules/wide-align": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
- "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
- "license": "ISC",
- "dependencies": {
- "string-width": "^1.0.2 || 2 || 3 || 4"
- }
- },
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
@@ -15227,6 +15028,7 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
@@ -15319,6 +15121,7 @@
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
"license": "ISC",
"engines": {
"node": ">=10"
@@ -15351,6 +15154,7 @@
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"cliui": "^8.0.1",
@@ -15369,6 +15173,7 @@
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
"license": "ISC",
"engines": {
"node": ">=12"
@@ -15404,6 +15209,7 @@
"integrity": "sha512-Bd5fw9wlIhtqCCxotZgdTOMwGm1a0u75wARVEY9HMs1X17trvA/lMi4+MGK5EUfYkXVTbX8UDiDKW4OgzHVUZw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
diff --git a/auto-claude-ui/package.json b/apps/frontend/package.json
similarity index 90%
rename from auto-claude-ui/package.json
rename to apps/frontend/package.json
index 73ea2fac..9c0d22c1 100644
--- a/auto-claude-ui/package.json
+++ b/apps/frontend/package.json
@@ -1,6 +1,7 @@
{
"name": "auto-claude-ui",
- "version": "2.7.1",
+ "version": "2.7.2",
+ "type": "module",
"description": "Desktop UI for Auto Claude autonomous coding framework",
"homepage": "https://github.com/AndyMik90/Auto-Claude",
"repository": {
@@ -13,14 +14,19 @@
"email": "119136210+AndyMik90@users.noreply.github.com"
},
"license": "AGPL-3.0",
+ "engines": {
+ "node": ">=24.0.0",
+ "npm": ">=10.0.0"
+ },
"scripts": {
- "postinstall": "node scripts/postinstall.js",
+ "postinstall": "node scripts/postinstall.cjs",
"dev": "electron-vite dev",
"dev:mcp": "electron-vite dev -- --remote-debugging-port=9222",
"build": "electron-vite build",
"start": "electron .",
"start:mcp": "electron . --remote-debugging-port=9222",
"preview": "electron-vite preview",
+ "rebuild": "electron-rebuild",
"package": "electron-vite build && electron-builder",
"package:mac": "electron-vite build && electron-builder --mac",
"package:win": "electron-vite build && electron-builder --win",
@@ -109,18 +115,9 @@
"vite": "^7.2.7",
"vitest": "^4.0.15"
},
- "pnpm": {
- "overrides": {
- "electron-builder-squirrel-windows": "^26.0.12",
- "dmg-builder": "^26.0.12",
- "node-pty": "npm:@lydell/node-pty@^1.1.0"
- },
- "onlyBuiltDependencies": [
- "@lydell/node-pty",
- "electron",
- "electron-winstaller",
- "esbuild"
- ]
+ "overrides": {
+ "electron-builder-squirrel-windows": "^26.0.12",
+ "dmg-builder": "^26.0.12"
},
"build": {
"appId": "com.autoclaude.ui",
@@ -151,7 +148,7 @@
"to": "icon.ico"
},
{
- "from": "../auto-claude",
+ "from": "../backend",
"to": "auto-claude",
"filter": [
"!**/.git",
@@ -201,6 +198,5 @@
"*.{ts,tsx}": [
"eslint --fix"
]
- },
- "packageManager": "pnpm@10.26.1+sha512.664074abc367d2c9324fdc18037097ce0a8f126034160f709928e9e9f95d98714347044e5c3164d65bd5da6c59c6be362b107546292a8eecb7999196e5ce58fa"
+ }
}
diff --git a/auto-claude-ui/postcss.config.js b/apps/frontend/postcss.config.cjs
similarity index 100%
rename from auto-claude-ui/postcss.config.js
rename to apps/frontend/postcss.config.cjs
diff --git a/auto-claude-ui/resources/entitlements.mac.plist b/apps/frontend/resources/entitlements.mac.plist
similarity index 100%
rename from auto-claude-ui/resources/entitlements.mac.plist
rename to apps/frontend/resources/entitlements.mac.plist
diff --git a/auto-claude-ui/resources/icon-256.png b/apps/frontend/resources/icon-256.png
similarity index 100%
rename from auto-claude-ui/resources/icon-256.png
rename to apps/frontend/resources/icon-256.png
diff --git a/auto-claude-ui/resources/icon.icns b/apps/frontend/resources/icon.icns
similarity index 100%
rename from auto-claude-ui/resources/icon.icns
rename to apps/frontend/resources/icon.icns
diff --git a/auto-claude-ui/resources/icon.ico b/apps/frontend/resources/icon.ico
similarity index 100%
rename from auto-claude-ui/resources/icon.ico
rename to apps/frontend/resources/icon.ico
diff --git a/auto-claude-ui/resources/icon.png b/apps/frontend/resources/icon.png
similarity index 100%
rename from auto-claude-ui/resources/icon.png
rename to apps/frontend/resources/icon.png
diff --git a/auto-claude-ui/scripts/download-prebuilds.js b/apps/frontend/scripts/download-prebuilds.cjs
similarity index 100%
rename from auto-claude-ui/scripts/download-prebuilds.js
rename to apps/frontend/scripts/download-prebuilds.cjs
diff --git a/auto-claude-ui/scripts/postinstall.js b/apps/frontend/scripts/postinstall.cjs
similarity index 99%
rename from auto-claude-ui/scripts/postinstall.js
rename to apps/frontend/scripts/postinstall.cjs
index b071cfd6..41a8ebe6 100644
--- a/auto-claude-ui/scripts/postinstall.js
+++ b/apps/frontend/scripts/postinstall.cjs
@@ -96,7 +96,7 @@ async function main() {
try {
// Dynamic import to handle case where the script doesn't exist yet
- const { downloadPrebuilds } = require('./download-prebuilds.js');
+ const { downloadPrebuilds } = require('./download-prebuilds.cjs');
const result = await downloadPrebuilds();
if (result.success) {
diff --git a/auto-claude-ui/src/__mocks__/electron.ts b/apps/frontend/src/__mocks__/electron.ts
similarity index 100%
rename from auto-claude-ui/src/__mocks__/electron.ts
rename to apps/frontend/src/__mocks__/electron.ts
diff --git a/auto-claude-ui/src/__tests__/integration/file-watcher.test.ts b/apps/frontend/src/__tests__/integration/file-watcher.test.ts
similarity index 100%
rename from auto-claude-ui/src/__tests__/integration/file-watcher.test.ts
rename to apps/frontend/src/__tests__/integration/file-watcher.test.ts
diff --git a/auto-claude-ui/src/__tests__/integration/ipc-bridge.test.ts b/apps/frontend/src/__tests__/integration/ipc-bridge.test.ts
similarity index 100%
rename from auto-claude-ui/src/__tests__/integration/ipc-bridge.test.ts
rename to apps/frontend/src/__tests__/integration/ipc-bridge.test.ts
diff --git a/auto-claude-ui/src/__tests__/integration/subprocess-spawn.test.ts b/apps/frontend/src/__tests__/integration/subprocess-spawn.test.ts
similarity index 100%
rename from auto-claude-ui/src/__tests__/integration/subprocess-spawn.test.ts
rename to apps/frontend/src/__tests__/integration/subprocess-spawn.test.ts
diff --git a/auto-claude-ui/src/__tests__/setup.ts b/apps/frontend/src/__tests__/setup.ts
similarity index 100%
rename from auto-claude-ui/src/__tests__/setup.ts
rename to apps/frontend/src/__tests__/setup.ts
diff --git a/auto-claude-ui/src/main/__tests__/ipc-handlers.test.ts b/apps/frontend/src/main/__tests__/ipc-handlers.test.ts
similarity index 100%
rename from auto-claude-ui/src/main/__tests__/ipc-handlers.test.ts
rename to apps/frontend/src/main/__tests__/ipc-handlers.test.ts
diff --git a/auto-claude-ui/src/main/__tests__/project-store.test.ts b/apps/frontend/src/main/__tests__/project-store.test.ts
similarity index 100%
rename from auto-claude-ui/src/main/__tests__/project-store.test.ts
rename to apps/frontend/src/main/__tests__/project-store.test.ts
diff --git a/auto-claude-ui/src/main/__tests__/rate-limit-auto-recovery.test.ts b/apps/frontend/src/main/__tests__/rate-limit-auto-recovery.test.ts
similarity index 100%
rename from auto-claude-ui/src/main/__tests__/rate-limit-auto-recovery.test.ts
rename to apps/frontend/src/main/__tests__/rate-limit-auto-recovery.test.ts
diff --git a/auto-claude-ui/src/main/__tests__/rate-limit-detector.test.ts b/apps/frontend/src/main/__tests__/rate-limit-detector.test.ts
similarity index 100%
rename from auto-claude-ui/src/main/__tests__/rate-limit-detector.test.ts
rename to apps/frontend/src/main/__tests__/rate-limit-detector.test.ts
diff --git a/auto-claude-ui/src/main/agent-manager.ts b/apps/frontend/src/main/agent-manager.ts
similarity index 100%
rename from auto-claude-ui/src/main/agent-manager.ts
rename to apps/frontend/src/main/agent-manager.ts
diff --git a/auto-claude-ui/src/main/agent/agent-events.ts b/apps/frontend/src/main/agent/agent-events.ts
similarity index 100%
rename from auto-claude-ui/src/main/agent/agent-events.ts
rename to apps/frontend/src/main/agent/agent-events.ts
diff --git a/auto-claude-ui/src/main/agent/agent-manager.ts b/apps/frontend/src/main/agent/agent-manager.ts
similarity index 100%
rename from auto-claude-ui/src/main/agent/agent-manager.ts
rename to apps/frontend/src/main/agent/agent-manager.ts
diff --git a/auto-claude-ui/src/main/agent/agent-process.ts b/apps/frontend/src/main/agent/agent-process.ts
similarity index 97%
rename from auto-claude-ui/src/main/agent/agent-process.ts
rename to apps/frontend/src/main/agent/agent-process.ts
index c3351cc4..fb0edd63 100644
--- a/auto-claude-ui/src/main/agent/agent-process.ts
+++ b/apps/frontend/src/main/agent/agent-process.ts
@@ -58,11 +58,13 @@ export class AgentProcessManager {
// Auto-detect from app location
const possiblePaths = [
- // Dev mode: from dist/main -> ../../auto-claude (sibling to auto-claude-ui)
- path.resolve(__dirname, '..', '..', '..', 'auto-claude'),
- // Alternative: from app root
- path.resolve(app.getAppPath(), '..', 'auto-claude'),
- // If running from repo root
+ // Dev mode: from dist/main -> ../../backend (apps/frontend/out/main -> apps/backend)
+ path.resolve(__dirname, '..', '..', '..', 'backend'),
+ // Alternative: from app root -> apps/backend
+ path.resolve(app.getAppPath(), '..', 'backend'),
+ // If running from repo root with apps structure
+ path.resolve(process.cwd(), 'apps', 'backend'),
+ // Legacy: auto-claude folder (for backwards compatibility)
path.resolve(process.cwd(), 'auto-claude')
];
diff --git a/auto-claude-ui/src/main/agent/agent-queue.ts b/apps/frontend/src/main/agent/agent-queue.ts
similarity index 100%
rename from auto-claude-ui/src/main/agent/agent-queue.ts
rename to apps/frontend/src/main/agent/agent-queue.ts
diff --git a/auto-claude-ui/src/main/agent/agent-state.ts b/apps/frontend/src/main/agent/agent-state.ts
similarity index 100%
rename from auto-claude-ui/src/main/agent/agent-state.ts
rename to apps/frontend/src/main/agent/agent-state.ts
diff --git a/auto-claude-ui/src/main/agent/index.ts b/apps/frontend/src/main/agent/index.ts
similarity index 100%
rename from auto-claude-ui/src/main/agent/index.ts
rename to apps/frontend/src/main/agent/index.ts
diff --git a/auto-claude-ui/src/main/agent/types.ts b/apps/frontend/src/main/agent/types.ts
similarity index 100%
rename from auto-claude-ui/src/main/agent/types.ts
rename to apps/frontend/src/main/agent/types.ts
diff --git a/auto-claude-ui/src/main/api-validation-service.ts b/apps/frontend/src/main/api-validation-service.ts
similarity index 100%
rename from auto-claude-ui/src/main/api-validation-service.ts
rename to apps/frontend/src/main/api-validation-service.ts
diff --git a/auto-claude-ui/src/main/app-updater.ts b/apps/frontend/src/main/app-updater.ts
similarity index 100%
rename from auto-claude-ui/src/main/app-updater.ts
rename to apps/frontend/src/main/app-updater.ts
diff --git a/auto-claude-ui/src/main/auto-claude-updater.ts b/apps/frontend/src/main/auto-claude-updater.ts
similarity index 100%
rename from auto-claude-ui/src/main/auto-claude-updater.ts
rename to apps/frontend/src/main/auto-claude-updater.ts
diff --git a/auto-claude-ui/src/main/changelog-service.ts b/apps/frontend/src/main/changelog-service.ts
similarity index 100%
rename from auto-claude-ui/src/main/changelog-service.ts
rename to apps/frontend/src/main/changelog-service.ts
diff --git a/auto-claude-ui/src/main/changelog/README.md b/apps/frontend/src/main/changelog/README.md
similarity index 100%
rename from auto-claude-ui/src/main/changelog/README.md
rename to apps/frontend/src/main/changelog/README.md
diff --git a/auto-claude-ui/src/main/changelog/changelog-service.ts b/apps/frontend/src/main/changelog/changelog-service.ts
similarity index 100%
rename from auto-claude-ui/src/main/changelog/changelog-service.ts
rename to apps/frontend/src/main/changelog/changelog-service.ts
diff --git a/auto-claude-ui/src/main/changelog/formatter.ts b/apps/frontend/src/main/changelog/formatter.ts
similarity index 100%
rename from auto-claude-ui/src/main/changelog/formatter.ts
rename to apps/frontend/src/main/changelog/formatter.ts
diff --git a/auto-claude-ui/src/main/changelog/generator.ts b/apps/frontend/src/main/changelog/generator.ts
similarity index 100%
rename from auto-claude-ui/src/main/changelog/generator.ts
rename to apps/frontend/src/main/changelog/generator.ts
diff --git a/auto-claude-ui/src/main/changelog/git-integration.ts b/apps/frontend/src/main/changelog/git-integration.ts
similarity index 100%
rename from auto-claude-ui/src/main/changelog/git-integration.ts
rename to apps/frontend/src/main/changelog/git-integration.ts
diff --git a/auto-claude-ui/src/main/changelog/index.ts b/apps/frontend/src/main/changelog/index.ts
similarity index 100%
rename from auto-claude-ui/src/main/changelog/index.ts
rename to apps/frontend/src/main/changelog/index.ts
diff --git a/auto-claude-ui/src/main/changelog/parser.ts b/apps/frontend/src/main/changelog/parser.ts
similarity index 100%
rename from auto-claude-ui/src/main/changelog/parser.ts
rename to apps/frontend/src/main/changelog/parser.ts
diff --git a/auto-claude-ui/src/main/changelog/types.ts b/apps/frontend/src/main/changelog/types.ts
similarity index 100%
rename from auto-claude-ui/src/main/changelog/types.ts
rename to apps/frontend/src/main/changelog/types.ts
diff --git a/auto-claude-ui/src/main/changelog/version-suggester.ts b/apps/frontend/src/main/changelog/version-suggester.ts
similarity index 100%
rename from auto-claude-ui/src/main/changelog/version-suggester.ts
rename to apps/frontend/src/main/changelog/version-suggester.ts
diff --git a/auto-claude-ui/src/main/claude-profile-manager.ts b/apps/frontend/src/main/claude-profile-manager.ts
similarity index 100%
rename from auto-claude-ui/src/main/claude-profile-manager.ts
rename to apps/frontend/src/main/claude-profile-manager.ts
diff --git a/auto-claude-ui/src/main/claude-profile/README.md b/apps/frontend/src/main/claude-profile/README.md
similarity index 100%
rename from auto-claude-ui/src/main/claude-profile/README.md
rename to apps/frontend/src/main/claude-profile/README.md
diff --git a/auto-claude-ui/src/main/claude-profile/index.ts b/apps/frontend/src/main/claude-profile/index.ts
similarity index 100%
rename from auto-claude-ui/src/main/claude-profile/index.ts
rename to apps/frontend/src/main/claude-profile/index.ts
diff --git a/auto-claude-ui/src/main/claude-profile/profile-scorer.ts b/apps/frontend/src/main/claude-profile/profile-scorer.ts
similarity index 100%
rename from auto-claude-ui/src/main/claude-profile/profile-scorer.ts
rename to apps/frontend/src/main/claude-profile/profile-scorer.ts
diff --git a/auto-claude-ui/src/main/claude-profile/profile-storage.ts b/apps/frontend/src/main/claude-profile/profile-storage.ts
similarity index 100%
rename from auto-claude-ui/src/main/claude-profile/profile-storage.ts
rename to apps/frontend/src/main/claude-profile/profile-storage.ts
diff --git a/auto-claude-ui/src/main/claude-profile/profile-utils.ts b/apps/frontend/src/main/claude-profile/profile-utils.ts
similarity index 100%
rename from auto-claude-ui/src/main/claude-profile/profile-utils.ts
rename to apps/frontend/src/main/claude-profile/profile-utils.ts
diff --git a/auto-claude-ui/src/main/claude-profile/rate-limit-manager.ts b/apps/frontend/src/main/claude-profile/rate-limit-manager.ts
similarity index 100%
rename from auto-claude-ui/src/main/claude-profile/rate-limit-manager.ts
rename to apps/frontend/src/main/claude-profile/rate-limit-manager.ts
diff --git a/auto-claude-ui/src/main/claude-profile/token-encryption.ts b/apps/frontend/src/main/claude-profile/token-encryption.ts
similarity index 100%
rename from auto-claude-ui/src/main/claude-profile/token-encryption.ts
rename to apps/frontend/src/main/claude-profile/token-encryption.ts
diff --git a/auto-claude-ui/src/main/claude-profile/types.ts b/apps/frontend/src/main/claude-profile/types.ts
similarity index 100%
rename from auto-claude-ui/src/main/claude-profile/types.ts
rename to apps/frontend/src/main/claude-profile/types.ts
diff --git a/auto-claude-ui/src/main/claude-profile/usage-monitor.ts b/apps/frontend/src/main/claude-profile/usage-monitor.ts
similarity index 100%
rename from auto-claude-ui/src/main/claude-profile/usage-monitor.ts
rename to apps/frontend/src/main/claude-profile/usage-monitor.ts
diff --git a/auto-claude-ui/src/main/claude-profile/usage-parser.ts b/apps/frontend/src/main/claude-profile/usage-parser.ts
similarity index 100%
rename from auto-claude-ui/src/main/claude-profile/usage-parser.ts
rename to apps/frontend/src/main/claude-profile/usage-parser.ts
diff --git a/auto-claude-ui/src/main/file-watcher.ts b/apps/frontend/src/main/file-watcher.ts
similarity index 100%
rename from auto-claude-ui/src/main/file-watcher.ts
rename to apps/frontend/src/main/file-watcher.ts
diff --git a/auto-claude-ui/src/main/index.ts b/apps/frontend/src/main/index.ts
similarity index 99%
rename from auto-claude-ui/src/main/index.ts
rename to apps/frontend/src/main/index.ts
index 2ba7f6d5..11cb39b4 100644
--- a/auto-claude-ui/src/main/index.ts
+++ b/apps/frontend/src/main/index.ts
@@ -49,7 +49,7 @@ function createWindow(): void {
trafficLightPosition: { x: 15, y: 10 },
icon: getIconPath(),
webPreferences: {
- preload: join(__dirname, '../preload/index.js'),
+ preload: join(__dirname, '../preload/index.mjs'),
sandbox: false,
contextIsolation: true,
nodeIntegration: false,
diff --git a/auto-claude-ui/src/main/insights-service.ts b/apps/frontend/src/main/insights-service.ts
similarity index 100%
rename from auto-claude-ui/src/main/insights-service.ts
rename to apps/frontend/src/main/insights-service.ts
diff --git a/auto-claude-ui/src/main/insights/README.md b/apps/frontend/src/main/insights/README.md
similarity index 100%
rename from auto-claude-ui/src/main/insights/README.md
rename to apps/frontend/src/main/insights/README.md
diff --git a/auto-claude-ui/src/main/insights/REFACTORING_NOTES.md b/apps/frontend/src/main/insights/REFACTORING_NOTES.md
similarity index 100%
rename from auto-claude-ui/src/main/insights/REFACTORING_NOTES.md
rename to apps/frontend/src/main/insights/REFACTORING_NOTES.md
diff --git a/auto-claude-ui/src/main/insights/config.ts b/apps/frontend/src/main/insights/config.ts
similarity index 100%
rename from auto-claude-ui/src/main/insights/config.ts
rename to apps/frontend/src/main/insights/config.ts
diff --git a/auto-claude-ui/src/main/insights/index.ts b/apps/frontend/src/main/insights/index.ts
similarity index 100%
rename from auto-claude-ui/src/main/insights/index.ts
rename to apps/frontend/src/main/insights/index.ts
diff --git a/auto-claude-ui/src/main/insights/insights-executor.ts b/apps/frontend/src/main/insights/insights-executor.ts
similarity index 100%
rename from auto-claude-ui/src/main/insights/insights-executor.ts
rename to apps/frontend/src/main/insights/insights-executor.ts
diff --git a/auto-claude-ui/src/main/insights/paths.ts b/apps/frontend/src/main/insights/paths.ts
similarity index 100%
rename from auto-claude-ui/src/main/insights/paths.ts
rename to apps/frontend/src/main/insights/paths.ts
diff --git a/auto-claude-ui/src/main/insights/session-manager.ts b/apps/frontend/src/main/insights/session-manager.ts
similarity index 100%
rename from auto-claude-ui/src/main/insights/session-manager.ts
rename to apps/frontend/src/main/insights/session-manager.ts
diff --git a/auto-claude-ui/src/main/insights/session-storage.ts b/apps/frontend/src/main/insights/session-storage.ts
similarity index 100%
rename from auto-claude-ui/src/main/insights/session-storage.ts
rename to apps/frontend/src/main/insights/session-storage.ts
diff --git a/auto-claude-ui/src/main/integrations/index.ts b/apps/frontend/src/main/integrations/index.ts
similarity index 100%
rename from auto-claude-ui/src/main/integrations/index.ts
rename to apps/frontend/src/main/integrations/index.ts
diff --git a/auto-claude-ui/src/main/integrations/types.ts b/apps/frontend/src/main/integrations/types.ts
similarity index 100%
rename from auto-claude-ui/src/main/integrations/types.ts
rename to apps/frontend/src/main/integrations/types.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/README.md b/apps/frontend/src/main/ipc-handlers/README.md
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/README.md
rename to apps/frontend/src/main/ipc-handlers/README.md
diff --git a/auto-claude-ui/src/main/ipc-handlers/agent-events-handlers.ts b/apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/agent-events-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/app-update-handlers.ts b/apps/frontend/src/main/ipc-handlers/app-update-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/app-update-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/app-update-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/autobuild-source-handlers.ts b/apps/frontend/src/main/ipc-handlers/autobuild-source-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/autobuild-source-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/autobuild-source-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/changelog-handlers.ts b/apps/frontend/src/main/ipc-handlers/changelog-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/changelog-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/changelog-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/changelog-handlers.ts.bk b/apps/frontend/src/main/ipc-handlers/changelog-handlers.ts.bk
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/changelog-handlers.ts.bk
rename to apps/frontend/src/main/ipc-handlers/changelog-handlers.ts.bk
diff --git a/auto-claude-ui/src/main/ipc-handlers/context-handlers.ts b/apps/frontend/src/main/ipc-handlers/context-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/context-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/context-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/context/README.md b/apps/frontend/src/main/ipc-handlers/context/README.md
similarity index 89%
rename from auto-claude-ui/src/main/ipc-handlers/context/README.md
rename to apps/frontend/src/main/ipc-handlers/context/README.md
index 0fc2269d..19de7f4a 100644
--- a/auto-claude-ui/src/main/ipc-handlers/context/README.md
+++ b/apps/frontend/src/main/ipc-handlers/context/README.md
@@ -1,6 +1,6 @@
# Context Handlers Module
-This directory contains the refactored context-related IPC handlers for the Auto Claude UI application. The handlers manage project context, memory systems (both file-based and Graphiti/FalkorDB), and project index operations.
+This directory contains the refactored context-related IPC handlers for the Auto Claude UI application. The handlers manage project context, memory systems (both file-based and Graphiti/LadybugDB), and project index operations.
## Architecture
@@ -18,12 +18,12 @@ Shared utility functions for environment configuration and parsing.
- `loadGlobalSettings()` - Load global application settings
- `isGraphitiEnabled(projectEnvVars)` - Check if Graphiti memory system is enabled
- `hasOpenAIKey(projectEnvVars, globalSettings)` - Check if OpenAI API key is available
-- `getGraphitiConnectionDetails(projectEnvVars)` - Get FalkorDB connection configuration
+- `getGraphitiConnectionDetails(projectEnvVars)` - Get LadybugDB connection configuration
**Types:**
- `EnvironmentVars` - Environment variable dictionary
- `GlobalSettings` - Global application settings
-- `GraphitiConnectionDetails` - FalkorDB connection details
+- `GraphitiConnectionDetails` - LadybugDB connection details
#### `memory-status-handlers.ts` (130 lines)
Handlers for checking Graphiti/memory system configuration status.
@@ -37,7 +37,7 @@ Handlers for checking Graphiti/memory system configuration status.
- `CONTEXT_MEMORY_STATUS` - Get memory system status
#### `memory-data-handlers.ts` (242 lines)
-Handlers for retrieving and searching memories (both file-based and FalkorDB).
+Handlers for retrieving and searching memories (both file-based and LadybugDB).
**Exports:**
- `loadFileBasedMemories(specsDir, limit)` - Load memories from spec files
@@ -45,11 +45,11 @@ Handlers for retrieving and searching memories (both file-based and FalkorDB).
- `registerMemoryDataHandlers(getMainWindow)` - Register IPC handlers
**IPC Channels:**
-- `CONTEXT_GET_MEMORIES` - Get recent memories (with FalkorDB fallback)
+- `CONTEXT_GET_MEMORIES` - Get recent memories (with LadybugDB fallback)
- `CONTEXT_SEARCH_MEMORIES` - Search memories by query
**Features:**
-- Dual-source memory loading (FalkorDB primary, file-based fallback)
+- Dual-source memory loading (LadybugDB primary, file-based fallback)
- Session insights extraction from spec directories
- Codebase map integration
- Semantic search support (when Graphiti is available)
@@ -103,7 +103,7 @@ context/index.ts (aggregator)
↓
├── utils.ts (no dependencies, pure utilities)
├── memory-status-handlers.ts (depends on: utils)
- ├── memory-data-handlers.ts (depends on: utils, falkordb-service)
+ ├── memory-data-handlers.ts (depends on: utils, ladybug-service)
└── project-context-handlers.ts (depends on: utils, memory-status-handlers, memory-data-handlers)
```
@@ -147,12 +147,12 @@ test('buildMemoryStatus returns correct status', () => {
- Add TypeScript interface documentation for all data structures
- Implement caching layer for frequently accessed context data
- Add telemetry for memory system performance
-- Support additional memory providers beyond FalkorDB
+- Support additional memory providers beyond LadybugDB
- Implement memory compression for large session insights
## Related Documentation
- [Project Memory System](../../../../auto-claude/memory.py)
- [Graphiti Memory Integration](../../../../auto-claude/graphiti_memory.py)
-- [FalkorDB Service](../../falkordb-service.ts)
+- [LadybugDB Integration](../../ladybug-service.ts)
- [IPC Channels](../../../shared/constants.ts)
diff --git a/auto-claude-ui/src/main/ipc-handlers/context/index.ts b/apps/frontend/src/main/ipc-handlers/context/index.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/context/index.ts
rename to apps/frontend/src/main/ipc-handlers/context/index.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/context/memory-data-handlers.ts b/apps/frontend/src/main/ipc-handlers/context/memory-data-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/context/memory-data-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/context/memory-data-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/context/memory-status-handlers.ts b/apps/frontend/src/main/ipc-handlers/context/memory-status-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/context/memory-status-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/context/memory-status-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/context/project-context-handlers.ts b/apps/frontend/src/main/ipc-handlers/context/project-context-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/context/project-context-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/context/project-context-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/context/utils.ts b/apps/frontend/src/main/ipc-handlers/context/utils.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/context/utils.ts
rename to apps/frontend/src/main/ipc-handlers/context/utils.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/env-handlers.ts b/apps/frontend/src/main/ipc-handlers/env-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/env-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/env-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/file-handlers.ts b/apps/frontend/src/main/ipc-handlers/file-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/file-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/file-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/github-handlers.ts b/apps/frontend/src/main/ipc-handlers/github-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/github-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/ARCHITECTURE.md b/apps/frontend/src/main/ipc-handlers/github/ARCHITECTURE.md
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/ARCHITECTURE.md
rename to apps/frontend/src/main/ipc-handlers/github/ARCHITECTURE.md
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/README.md b/apps/frontend/src/main/ipc-handlers/github/README.md
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/README.md
rename to apps/frontend/src/main/ipc-handlers/github/README.md
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/__tests__/oauth-handlers.spec.ts b/apps/frontend/src/main/ipc-handlers/github/__tests__/oauth-handlers.spec.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/__tests__/oauth-handlers.spec.ts
rename to apps/frontend/src/main/ipc-handlers/github/__tests__/oauth-handlers.spec.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/import-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/import-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/import-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/github/import-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/index.ts b/apps/frontend/src/main/ipc-handlers/github/index.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/index.ts
rename to apps/frontend/src/main/ipc-handlers/github/index.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/investigation-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/investigation-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/issue-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/issue-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/issue-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/github/issue-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/oauth-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/oauth-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/oauth-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/github/oauth-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/release-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/release-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/release-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/github/release-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/repository-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/repository-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/repository-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/github/repository-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/spec-utils.ts b/apps/frontend/src/main/ipc-handlers/github/spec-utils.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/spec-utils.ts
rename to apps/frontend/src/main/ipc-handlers/github/spec-utils.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/types.ts b/apps/frontend/src/main/ipc-handlers/github/types.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/types.ts
rename to apps/frontend/src/main/ipc-handlers/github/types.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/github/utils.ts b/apps/frontend/src/main/ipc-handlers/github/utils.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/github/utils.ts
rename to apps/frontend/src/main/ipc-handlers/github/utils.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation-handlers.ts b/apps/frontend/src/main/ipc-handlers/ideation-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/ideation-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/ideation-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/file-utils.ts b/apps/frontend/src/main/ipc-handlers/ideation/file-utils.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/ideation/file-utils.ts
rename to apps/frontend/src/main/ipc-handlers/ideation/file-utils.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/generation-handlers.ts b/apps/frontend/src/main/ipc-handlers/ideation/generation-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/ideation/generation-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/ideation/generation-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/idea-manager.ts b/apps/frontend/src/main/ipc-handlers/ideation/idea-manager.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/ideation/idea-manager.ts
rename to apps/frontend/src/main/ipc-handlers/ideation/idea-manager.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/index.ts b/apps/frontend/src/main/ipc-handlers/ideation/index.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/ideation/index.ts
rename to apps/frontend/src/main/ipc-handlers/ideation/index.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/session-manager.ts b/apps/frontend/src/main/ipc-handlers/ideation/session-manager.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/ideation/session-manager.ts
rename to apps/frontend/src/main/ipc-handlers/ideation/session-manager.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/task-converter.ts b/apps/frontend/src/main/ipc-handlers/ideation/task-converter.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/ideation/task-converter.ts
rename to apps/frontend/src/main/ipc-handlers/ideation/task-converter.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/transformers.ts b/apps/frontend/src/main/ipc-handlers/ideation/transformers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/ideation/transformers.ts
rename to apps/frontend/src/main/ipc-handlers/ideation/transformers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/types.ts b/apps/frontend/src/main/ipc-handlers/ideation/types.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/ideation/types.ts
rename to apps/frontend/src/main/ipc-handlers/ideation/types.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/index.ts b/apps/frontend/src/main/ipc-handlers/index.ts
similarity index 97%
rename from auto-claude-ui/src/main/ipc-handlers/index.ts
rename to apps/frontend/src/main/ipc-handlers/index.ts
index fbb2017f..c79971bb 100644
--- a/auto-claude-ui/src/main/ipc-handlers/index.ts
+++ b/apps/frontend/src/main/ipc-handlers/index.ts
@@ -26,7 +26,7 @@ import { registerAutobuildSourceHandlers } from './autobuild-source-handlers';
import { registerIdeationHandlers } from './ideation-handlers';
import { registerChangelogHandlers } from './changelog-handlers';
import { registerInsightsHandlers } from './insights-handlers';
-import { registerDockerHandlers } from './docker-handlers';
+import { registerMemoryHandlers } from './memory-handlers';
import { registerAppUpdateHandlers } from './app-update-handlers';
import { notificationService } from '../notification-service';
@@ -93,7 +93,7 @@ export function setupIpcHandlers(
registerInsightsHandlers(getMainWindow);
// Memory & infrastructure handlers (for Graphiti/LadybugDB)
- registerDockerHandlers();
+ registerMemoryHandlers();
// App auto-update handlers
registerAppUpdateHandlers();
@@ -118,6 +118,6 @@ export {
registerIdeationHandlers,
registerChangelogHandlers,
registerInsightsHandlers,
- registerDockerHandlers,
+ registerMemoryHandlers,
registerAppUpdateHandlers
};
diff --git a/auto-claude-ui/src/main/ipc-handlers/insights-handlers.ts b/apps/frontend/src/main/ipc-handlers/insights-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/insights-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/insights-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/linear-handlers.ts b/apps/frontend/src/main/ipc-handlers/linear-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/linear-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/linear-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/memory-handlers.ts b/apps/frontend/src/main/ipc-handlers/memory-handlers.ts
similarity index 98%
rename from auto-claude-ui/src/main/ipc-handlers/memory-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/memory-handlers.ts
index 344e4c65..b155b38d 100644
--- a/auto-claude-ui/src/main/ipc-handlers/memory-handlers.ts
+++ b/apps/frontend/src/main/ipc-handlers/memory-handlers.ts
@@ -79,9 +79,12 @@ async function executeOllamaDetector(
// Find the ollama_model_detector.py script
const possiblePaths = [
+ // Development paths
+ path.resolve(__dirname, '..', '..', '..', '..', 'backend', 'ollama_model_detector.py'),
+ path.resolve(process.cwd(), 'apps', 'backend', 'ollama_model_detector.py'),
+ // Legacy paths (for backwards compatibility)
path.resolve(__dirname, '..', '..', '..', 'auto-claude', 'ollama_model_detector.py'),
path.resolve(process.cwd(), 'auto-claude', 'ollama_model_detector.py'),
- path.resolve(process.cwd(), '..', 'auto-claude', 'ollama_model_detector.py'),
];
let scriptPath: string | null = null;
diff --git a/auto-claude-ui/src/main/ipc-handlers/project-handlers.ts b/apps/frontend/src/main/ipc-handlers/project-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/project-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/project-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/roadmap-handlers.ts b/apps/frontend/src/main/ipc-handlers/roadmap-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/roadmap-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/roadmap-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/context-roadmap-section.txt b/apps/frontend/src/main/ipc-handlers/sections/context-roadmap-section.txt
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/sections/context-roadmap-section.txt
rename to apps/frontend/src/main/ipc-handlers/sections/context-roadmap-section.txt
diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/context_extracted.txt b/apps/frontend/src/main/ipc-handlers/sections/context_extracted.txt
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/sections/context_extracted.txt
rename to apps/frontend/src/main/ipc-handlers/sections/context_extracted.txt
diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/ideation-insights-section.txt b/apps/frontend/src/main/ipc-handlers/sections/ideation-insights-section.txt
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/sections/ideation-insights-section.txt
rename to apps/frontend/src/main/ipc-handlers/sections/ideation-insights-section.txt
diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/integration-section.txt b/apps/frontend/src/main/ipc-handlers/sections/integration-section.txt
similarity index 99%
rename from auto-claude-ui/src/main/ipc-handlers/sections/integration-section.txt
rename to apps/frontend/src/main/ipc-handlers/sections/integration-section.txt
index f137af7f..5432d011 100644
--- a/auto-claude-ui/src/main/ipc-handlers/sections/integration-section.txt
+++ b/apps/frontend/src/main/ipc-handlers/sections/integration-section.txt
@@ -121,7 +121,7 @@ ${existingVars['GITHUB_AUTO_SYNC'] !== undefined ? `GITHUB_AUTO_SYNC=${existingV
${existingVars['ENABLE_FANCY_UI'] !== undefined ? `ENABLE_FANCY_UI=${existingVars['ENABLE_FANCY_UI']}` : '# ENABLE_FANCY_UI=true'}
# =============================================================================
-# GRAPHITI MEMORY INTEGRATION (OPTIONAL)
+# GRAPHITI MEMORY INTEGRATION (REQUIRED)
# =============================================================================
${existingVars['GRAPHITI_ENABLED'] ? `GRAPHITI_ENABLED=${existingVars['GRAPHITI_ENABLED']}` : '# GRAPHITI_ENABLED=false'}
${existingVars['OPENAI_API_KEY'] ? `OPENAI_API_KEY=${existingVars['OPENAI_API_KEY']}` : '# OPENAI_API_KEY='}
diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/roadmap_extracted.txt b/apps/frontend/src/main/ipc-handlers/sections/roadmap_extracted.txt
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/sections/roadmap_extracted.txt
rename to apps/frontend/src/main/ipc-handlers/sections/roadmap_extracted.txt
diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/task-section.txt b/apps/frontend/src/main/ipc-handlers/sections/task-section.txt
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/sections/task-section.txt
rename to apps/frontend/src/main/ipc-handlers/sections/task-section.txt
diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/task_extracted.txt b/apps/frontend/src/main/ipc-handlers/sections/task_extracted.txt
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/sections/task_extracted.txt
rename to apps/frontend/src/main/ipc-handlers/sections/task_extracted.txt
diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/terminal-section.txt b/apps/frontend/src/main/ipc-handlers/sections/terminal-section.txt
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/sections/terminal-section.txt
rename to apps/frontend/src/main/ipc-handlers/sections/terminal-section.txt
diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/terminal_extracted.txt b/apps/frontend/src/main/ipc-handlers/sections/terminal_extracted.txt
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/sections/terminal_extracted.txt
rename to apps/frontend/src/main/ipc-handlers/sections/terminal_extracted.txt
diff --git a/auto-claude-ui/src/main/ipc-handlers/settings-handlers.ts b/apps/frontend/src/main/ipc-handlers/settings-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/settings-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/settings-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/task-handlers.ts b/apps/frontend/src/main/ipc-handlers/task-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/task-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/task-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/task/README.md b/apps/frontend/src/main/ipc-handlers/task/README.md
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/task/README.md
rename to apps/frontend/src/main/ipc-handlers/task/README.md
diff --git a/auto-claude-ui/src/main/ipc-handlers/task/REFACTORING_SUMMARY.md b/apps/frontend/src/main/ipc-handlers/task/REFACTORING_SUMMARY.md
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/task/REFACTORING_SUMMARY.md
rename to apps/frontend/src/main/ipc-handlers/task/REFACTORING_SUMMARY.md
diff --git a/auto-claude-ui/src/main/ipc-handlers/task/archive-handlers.ts b/apps/frontend/src/main/ipc-handlers/task/archive-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/task/archive-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/task/archive-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/task/crud-handlers.ts b/apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/task/crud-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/task/execution-handlers.ts b/apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/task/execution-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/task/index.ts b/apps/frontend/src/main/ipc-handlers/task/index.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/task/index.ts
rename to apps/frontend/src/main/ipc-handlers/task/index.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/task/logs-handlers.ts b/apps/frontend/src/main/ipc-handlers/task/logs-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/task/logs-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/task/logs-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/task/shared.ts b/apps/frontend/src/main/ipc-handlers/task/shared.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/task/shared.ts
rename to apps/frontend/src/main/ipc-handlers/task/shared.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/task/worktree-handlers.ts b/apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/task/worktree-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/terminal-handlers.ts b/apps/frontend/src/main/ipc-handlers/terminal-handlers.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/terminal-handlers.ts
rename to apps/frontend/src/main/ipc-handlers/terminal-handlers.ts
diff --git a/auto-claude-ui/src/main/ipc-handlers/utils.ts b/apps/frontend/src/main/ipc-handlers/utils.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-handlers/utils.ts
rename to apps/frontend/src/main/ipc-handlers/utils.ts
diff --git a/auto-claude-ui/src/main/ipc-setup.ts b/apps/frontend/src/main/ipc-setup.ts
similarity index 100%
rename from auto-claude-ui/src/main/ipc-setup.ts
rename to apps/frontend/src/main/ipc-setup.ts
diff --git a/auto-claude-ui/src/main/log-service.ts b/apps/frontend/src/main/log-service.ts
similarity index 100%
rename from auto-claude-ui/src/main/log-service.ts
rename to apps/frontend/src/main/log-service.ts
diff --git a/auto-claude-ui/src/main/memory-service.ts b/apps/frontend/src/main/memory-service.ts
similarity index 100%
rename from auto-claude-ui/src/main/memory-service.ts
rename to apps/frontend/src/main/memory-service.ts
diff --git a/auto-claude-ui/src/main/notification-service.ts b/apps/frontend/src/main/notification-service.ts
similarity index 100%
rename from auto-claude-ui/src/main/notification-service.ts
rename to apps/frontend/src/main/notification-service.ts
diff --git a/auto-claude-ui/src/main/project-initializer.ts b/apps/frontend/src/main/project-initializer.ts
similarity index 100%
rename from auto-claude-ui/src/main/project-initializer.ts
rename to apps/frontend/src/main/project-initializer.ts
diff --git a/auto-claude-ui/src/main/project-store.ts b/apps/frontend/src/main/project-store.ts
similarity index 100%
rename from auto-claude-ui/src/main/project-store.ts
rename to apps/frontend/src/main/project-store.ts
diff --git a/auto-claude-ui/src/main/python-detector.ts b/apps/frontend/src/main/python-detector.ts
similarity index 100%
rename from auto-claude-ui/src/main/python-detector.ts
rename to apps/frontend/src/main/python-detector.ts
diff --git a/auto-claude-ui/src/main/python-env-manager.ts b/apps/frontend/src/main/python-env-manager.ts
similarity index 100%
rename from auto-claude-ui/src/main/python-env-manager.ts
rename to apps/frontend/src/main/python-env-manager.ts
diff --git a/auto-claude-ui/src/main/rate-limit-detector.ts b/apps/frontend/src/main/rate-limit-detector.ts
similarity index 100%
rename from auto-claude-ui/src/main/rate-limit-detector.ts
rename to apps/frontend/src/main/rate-limit-detector.ts
diff --git a/auto-claude-ui/src/main/release-service.ts b/apps/frontend/src/main/release-service.ts
similarity index 100%
rename from auto-claude-ui/src/main/release-service.ts
rename to apps/frontend/src/main/release-service.ts
diff --git a/auto-claude-ui/src/main/task-log-service.ts b/apps/frontend/src/main/task-log-service.ts
similarity index 100%
rename from auto-claude-ui/src/main/task-log-service.ts
rename to apps/frontend/src/main/task-log-service.ts
diff --git a/auto-claude-ui/src/main/terminal-manager.ts b/apps/frontend/src/main/terminal-manager.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal-manager.ts
rename to apps/frontend/src/main/terminal-manager.ts
diff --git a/auto-claude-ui/src/main/terminal-name-generator.ts b/apps/frontend/src/main/terminal-name-generator.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal-name-generator.ts
rename to apps/frontend/src/main/terminal-name-generator.ts
diff --git a/auto-claude-ui/src/main/terminal-session-store.ts b/apps/frontend/src/main/terminal-session-store.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal-session-store.ts
rename to apps/frontend/src/main/terminal-session-store.ts
diff --git a/auto-claude-ui/src/main/terminal/claude-integration-handler.ts b/apps/frontend/src/main/terminal/claude-integration-handler.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal/claude-integration-handler.ts
rename to apps/frontend/src/main/terminal/claude-integration-handler.ts
diff --git a/auto-claude-ui/src/main/terminal/index.ts b/apps/frontend/src/main/terminal/index.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal/index.ts
rename to apps/frontend/src/main/terminal/index.ts
diff --git a/auto-claude-ui/src/main/terminal/output-parser.ts b/apps/frontend/src/main/terminal/output-parser.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal/output-parser.ts
rename to apps/frontend/src/main/terminal/output-parser.ts
diff --git a/auto-claude-ui/src/main/terminal/pty-daemon-client.ts b/apps/frontend/src/main/terminal/pty-daemon-client.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal/pty-daemon-client.ts
rename to apps/frontend/src/main/terminal/pty-daemon-client.ts
diff --git a/auto-claude-ui/src/main/terminal/pty-daemon.ts b/apps/frontend/src/main/terminal/pty-daemon.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal/pty-daemon.ts
rename to apps/frontend/src/main/terminal/pty-daemon.ts
diff --git a/auto-claude-ui/src/main/terminal/pty-manager.ts b/apps/frontend/src/main/terminal/pty-manager.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal/pty-manager.ts
rename to apps/frontend/src/main/terminal/pty-manager.ts
diff --git a/auto-claude-ui/src/main/terminal/session-handler.ts b/apps/frontend/src/main/terminal/session-handler.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal/session-handler.ts
rename to apps/frontend/src/main/terminal/session-handler.ts
diff --git a/auto-claude-ui/src/main/terminal/session-persistence.ts b/apps/frontend/src/main/terminal/session-persistence.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal/session-persistence.ts
rename to apps/frontend/src/main/terminal/session-persistence.ts
diff --git a/auto-claude-ui/src/main/terminal/terminal-event-handler.ts b/apps/frontend/src/main/terminal/terminal-event-handler.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal/terminal-event-handler.ts
rename to apps/frontend/src/main/terminal/terminal-event-handler.ts
diff --git a/auto-claude-ui/src/main/terminal/terminal-lifecycle.ts b/apps/frontend/src/main/terminal/terminal-lifecycle.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal/terminal-lifecycle.ts
rename to apps/frontend/src/main/terminal/terminal-lifecycle.ts
diff --git a/auto-claude-ui/src/main/terminal/terminal-manager.ts b/apps/frontend/src/main/terminal/terminal-manager.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal/terminal-manager.ts
rename to apps/frontend/src/main/terminal/terminal-manager.ts
diff --git a/auto-claude-ui/src/main/terminal/types.ts b/apps/frontend/src/main/terminal/types.ts
similarity index 100%
rename from auto-claude-ui/src/main/terminal/types.ts
rename to apps/frontend/src/main/terminal/types.ts
diff --git a/auto-claude-ui/src/main/title-generator.ts b/apps/frontend/src/main/title-generator.ts
similarity index 100%
rename from auto-claude-ui/src/main/title-generator.ts
rename to apps/frontend/src/main/title-generator.ts
diff --git a/auto-claude-ui/src/main/updater/config.ts b/apps/frontend/src/main/updater/config.ts
similarity index 100%
rename from auto-claude-ui/src/main/updater/config.ts
rename to apps/frontend/src/main/updater/config.ts
diff --git a/auto-claude-ui/src/main/updater/file-operations.ts b/apps/frontend/src/main/updater/file-operations.ts
similarity index 100%
rename from auto-claude-ui/src/main/updater/file-operations.ts
rename to apps/frontend/src/main/updater/file-operations.ts
diff --git a/auto-claude-ui/src/main/updater/http-client.ts b/apps/frontend/src/main/updater/http-client.ts
similarity index 100%
rename from auto-claude-ui/src/main/updater/http-client.ts
rename to apps/frontend/src/main/updater/http-client.ts
diff --git a/auto-claude-ui/src/main/updater/path-resolver.ts b/apps/frontend/src/main/updater/path-resolver.ts
similarity index 63%
rename from auto-claude-ui/src/main/updater/path-resolver.ts
rename to apps/frontend/src/main/updater/path-resolver.ts
index 4a19ffcb..c9aecc79 100644
--- a/auto-claude-ui/src/main/updater/path-resolver.ts
+++ b/apps/frontend/src/main/updater/path-resolver.ts
@@ -7,21 +7,22 @@ import path from 'path';
import { app } from 'electron';
/**
- * Get the path to the bundled auto-claude source
+ * Get the path to the bundled backend source
*/
export function getBundledSourcePath(): string {
// In production, use app resources
- // In development, use the repo's auto-claude folder
+ // In development, use the repo's apps/backend folder
if (app.isPackaged) {
- return path.join(process.resourcesPath, 'auto-claude');
+ return path.join(process.resourcesPath, 'backend');
}
- // Development mode - look for auto-claude in various locations
+ // Development mode - look for backend in various locations
const possiblePaths = [
- path.join(app.getAppPath(), '..', 'auto-claude'),
- path.join(app.getAppPath(), '..', '..', 'auto-claude'),
- path.join(process.cwd(), 'auto-claude'),
- path.join(process.cwd(), '..', 'auto-claude')
+ // New structure: apps/frontend -> apps/backend
+ path.join(app.getAppPath(), '..', 'backend'),
+ path.join(app.getAppPath(), '..', '..', 'apps', 'backend'),
+ path.join(process.cwd(), 'apps', 'backend'),
+ path.join(process.cwd(), '..', 'backend')
];
for (const p of possiblePaths) {
@@ -31,7 +32,7 @@ export function getBundledSourcePath(): string {
}
// Fallback
- return path.join(app.getAppPath(), '..', 'auto-claude');
+ return path.join(app.getAppPath(), '..', 'backend');
}
/**
@@ -47,7 +48,7 @@ export function getUpdateCachePath(): string {
export function getEffectiveSourcePath(): string {
if (app.isPackaged) {
// Check for user-updated source first
- const overridePath = path.join(app.getPath('userData'), 'auto-claude-source');
+ const overridePath = path.join(app.getPath('userData'), 'backend-source');
if (existsSync(overridePath)) {
return overridePath;
}
@@ -62,7 +63,7 @@ export function getEffectiveSourcePath(): string {
export function getUpdateTargetPath(): string {
if (app.isPackaged) {
// For packaged apps, store in userData as a source override
- return path.join(app.getPath('userData'), 'auto-claude-source');
+ return path.join(app.getPath('userData'), 'backend-source');
} else {
// In development, update the actual source
return getBundledSourcePath();
diff --git a/auto-claude-ui/src/main/updater/types.ts b/apps/frontend/src/main/updater/types.ts
similarity index 100%
rename from auto-claude-ui/src/main/updater/types.ts
rename to apps/frontend/src/main/updater/types.ts
diff --git a/auto-claude-ui/src/main/updater/update-checker.ts b/apps/frontend/src/main/updater/update-checker.ts
similarity index 100%
rename from auto-claude-ui/src/main/updater/update-checker.ts
rename to apps/frontend/src/main/updater/update-checker.ts
diff --git a/auto-claude-ui/src/main/updater/update-installer.ts b/apps/frontend/src/main/updater/update-installer.ts
similarity index 100%
rename from auto-claude-ui/src/main/updater/update-installer.ts
rename to apps/frontend/src/main/updater/update-installer.ts
diff --git a/auto-claude-ui/src/main/updater/update-status.ts b/apps/frontend/src/main/updater/update-status.ts
similarity index 100%
rename from auto-claude-ui/src/main/updater/update-status.ts
rename to apps/frontend/src/main/updater/update-status.ts
diff --git a/auto-claude-ui/src/main/updater/version-manager.ts b/apps/frontend/src/main/updater/version-manager.ts
similarity index 100%
rename from auto-claude-ui/src/main/updater/version-manager.ts
rename to apps/frontend/src/main/updater/version-manager.ts
diff --git a/auto-claude-ui/src/preload/api/agent-api.ts b/apps/frontend/src/preload/api/agent-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/agent-api.ts
rename to apps/frontend/src/preload/api/agent-api.ts
diff --git a/auto-claude-ui/src/preload/api/app-update-api.ts b/apps/frontend/src/preload/api/app-update-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/app-update-api.ts
rename to apps/frontend/src/preload/api/app-update-api.ts
diff --git a/auto-claude-ui/src/preload/api/file-api.ts b/apps/frontend/src/preload/api/file-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/file-api.ts
rename to apps/frontend/src/preload/api/file-api.ts
diff --git a/auto-claude-ui/src/preload/api/index.ts b/apps/frontend/src/preload/api/index.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/index.ts
rename to apps/frontend/src/preload/api/index.ts
diff --git a/auto-claude-ui/src/preload/api/modules/README.md b/apps/frontend/src/preload/api/modules/README.md
similarity index 100%
rename from auto-claude-ui/src/preload/api/modules/README.md
rename to apps/frontend/src/preload/api/modules/README.md
diff --git a/auto-claude-ui/src/preload/api/modules/autobuild-api.ts b/apps/frontend/src/preload/api/modules/autobuild-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/modules/autobuild-api.ts
rename to apps/frontend/src/preload/api/modules/autobuild-api.ts
diff --git a/auto-claude-ui/src/preload/api/modules/changelog-api.ts b/apps/frontend/src/preload/api/modules/changelog-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/modules/changelog-api.ts
rename to apps/frontend/src/preload/api/modules/changelog-api.ts
diff --git a/auto-claude-ui/src/preload/api/modules/github-api.ts b/apps/frontend/src/preload/api/modules/github-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/modules/github-api.ts
rename to apps/frontend/src/preload/api/modules/github-api.ts
diff --git a/auto-claude-ui/src/preload/api/modules/ideation-api.ts b/apps/frontend/src/preload/api/modules/ideation-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/modules/ideation-api.ts
rename to apps/frontend/src/preload/api/modules/ideation-api.ts
diff --git a/auto-claude-ui/src/preload/api/modules/index.ts b/apps/frontend/src/preload/api/modules/index.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/modules/index.ts
rename to apps/frontend/src/preload/api/modules/index.ts
diff --git a/auto-claude-ui/src/preload/api/modules/insights-api.ts b/apps/frontend/src/preload/api/modules/insights-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/modules/insights-api.ts
rename to apps/frontend/src/preload/api/modules/insights-api.ts
diff --git a/auto-claude-ui/src/preload/api/modules/ipc-utils.ts b/apps/frontend/src/preload/api/modules/ipc-utils.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/modules/ipc-utils.ts
rename to apps/frontend/src/preload/api/modules/ipc-utils.ts
diff --git a/auto-claude-ui/src/preload/api/modules/linear-api.ts b/apps/frontend/src/preload/api/modules/linear-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/modules/linear-api.ts
rename to apps/frontend/src/preload/api/modules/linear-api.ts
diff --git a/auto-claude-ui/src/preload/api/modules/roadmap-api.ts b/apps/frontend/src/preload/api/modules/roadmap-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/modules/roadmap-api.ts
rename to apps/frontend/src/preload/api/modules/roadmap-api.ts
diff --git a/auto-claude-ui/src/preload/api/modules/shell-api.ts b/apps/frontend/src/preload/api/modules/shell-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/modules/shell-api.ts
rename to apps/frontend/src/preload/api/modules/shell-api.ts
diff --git a/auto-claude-ui/src/preload/api/project-api.ts b/apps/frontend/src/preload/api/project-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/project-api.ts
rename to apps/frontend/src/preload/api/project-api.ts
diff --git a/auto-claude-ui/src/preload/api/settings-api.ts b/apps/frontend/src/preload/api/settings-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/settings-api.ts
rename to apps/frontend/src/preload/api/settings-api.ts
diff --git a/auto-claude-ui/src/preload/api/task-api.ts b/apps/frontend/src/preload/api/task-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/task-api.ts
rename to apps/frontend/src/preload/api/task-api.ts
diff --git a/auto-claude-ui/src/preload/api/terminal-api.ts b/apps/frontend/src/preload/api/terminal-api.ts
similarity index 100%
rename from auto-claude-ui/src/preload/api/terminal-api.ts
rename to apps/frontend/src/preload/api/terminal-api.ts
diff --git a/auto-claude-ui/src/preload/index.ts b/apps/frontend/src/preload/index.ts
similarity index 100%
rename from auto-claude-ui/src/preload/index.ts
rename to apps/frontend/src/preload/index.ts
diff --git a/auto-claude-ui/src/renderer/App.tsx b/apps/frontend/src/renderer/App.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/App.tsx
rename to apps/frontend/src/renderer/App.tsx
diff --git a/auto-claude-ui/src/renderer/__tests__/OAuthStep.test.tsx b/apps/frontend/src/renderer/__tests__/OAuthStep.test.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/__tests__/OAuthStep.test.tsx
rename to apps/frontend/src/renderer/__tests__/OAuthStep.test.tsx
diff --git a/auto-claude-ui/src/renderer/__tests__/TaskEditDialog.test.ts b/apps/frontend/src/renderer/__tests__/TaskEditDialog.test.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/__tests__/TaskEditDialog.test.ts
rename to apps/frontend/src/renderer/__tests__/TaskEditDialog.test.ts
diff --git a/auto-claude-ui/src/renderer/__tests__/project-store-tabs.test.ts b/apps/frontend/src/renderer/__tests__/project-store-tabs.test.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/__tests__/project-store-tabs.test.ts
rename to apps/frontend/src/renderer/__tests__/project-store-tabs.test.ts
diff --git a/auto-claude-ui/src/renderer/__tests__/roadmap-store.test.ts b/apps/frontend/src/renderer/__tests__/roadmap-store.test.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/__tests__/roadmap-store.test.ts
rename to apps/frontend/src/renderer/__tests__/roadmap-store.test.ts
diff --git a/auto-claude-ui/src/renderer/__tests__/task-store.test.ts b/apps/frontend/src/renderer/__tests__/task-store.test.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/__tests__/task-store.test.ts
rename to apps/frontend/src/renderer/__tests__/task-store.test.ts
diff --git a/auto-claude-ui/src/renderer/components/AddFeatureDialog.tsx b/apps/frontend/src/renderer/components/AddFeatureDialog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/AddFeatureDialog.tsx
rename to apps/frontend/src/renderer/components/AddFeatureDialog.tsx
diff --git a/auto-claude-ui/src/renderer/components/AddProjectModal.tsx b/apps/frontend/src/renderer/components/AddProjectModal.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/AddProjectModal.tsx
rename to apps/frontend/src/renderer/components/AddProjectModal.tsx
diff --git a/auto-claude-ui/src/renderer/components/AgentProfileSelector.tsx b/apps/frontend/src/renderer/components/AgentProfileSelector.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/AgentProfileSelector.tsx
rename to apps/frontend/src/renderer/components/AgentProfileSelector.tsx
diff --git a/auto-claude-ui/src/renderer/components/AgentProfiles.tsx b/apps/frontend/src/renderer/components/AgentProfiles.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/AgentProfiles.tsx
rename to apps/frontend/src/renderer/components/AgentProfiles.tsx
diff --git a/auto-claude-ui/src/renderer/components/AppSettings.tsx b/apps/frontend/src/renderer/components/AppSettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/AppSettings.tsx
rename to apps/frontend/src/renderer/components/AppSettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/AppUpdateNotification.tsx b/apps/frontend/src/renderer/components/AppUpdateNotification.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/AppUpdateNotification.tsx
rename to apps/frontend/src/renderer/components/AppUpdateNotification.tsx
diff --git a/auto-claude-ui/src/renderer/components/Changelog.tsx b/apps/frontend/src/renderer/components/Changelog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/Changelog.tsx
rename to apps/frontend/src/renderer/components/Changelog.tsx
diff --git a/auto-claude-ui/src/renderer/components/ChatHistorySidebar.tsx b/apps/frontend/src/renderer/components/ChatHistorySidebar.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ChatHistorySidebar.tsx
rename to apps/frontend/src/renderer/components/ChatHistorySidebar.tsx
diff --git a/auto-claude-ui/src/renderer/components/CompetitorAnalysisDialog.tsx b/apps/frontend/src/renderer/components/CompetitorAnalysisDialog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/CompetitorAnalysisDialog.tsx
rename to apps/frontend/src/renderer/components/CompetitorAnalysisDialog.tsx
diff --git a/auto-claude-ui/src/renderer/components/CompetitorAnalysisViewer.tsx b/apps/frontend/src/renderer/components/CompetitorAnalysisViewer.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/CompetitorAnalysisViewer.tsx
rename to apps/frontend/src/renderer/components/CompetitorAnalysisViewer.tsx
diff --git a/auto-claude-ui/src/renderer/components/Context.tsx b/apps/frontend/src/renderer/components/Context.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/Context.tsx
rename to apps/frontend/src/renderer/components/Context.tsx
diff --git a/auto-claude-ui/src/renderer/components/CustomModelModal.tsx b/apps/frontend/src/renderer/components/CustomModelModal.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/CustomModelModal.tsx
rename to apps/frontend/src/renderer/components/CustomModelModal.tsx
diff --git a/auto-claude-ui/src/renderer/components/EnvConfigModal.tsx b/apps/frontend/src/renderer/components/EnvConfigModal.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/EnvConfigModal.tsx
rename to apps/frontend/src/renderer/components/EnvConfigModal.tsx
diff --git a/auto-claude-ui/src/renderer/components/ExistingCompetitorAnalysisDialog.tsx b/apps/frontend/src/renderer/components/ExistingCompetitorAnalysisDialog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ExistingCompetitorAnalysisDialog.tsx
rename to apps/frontend/src/renderer/components/ExistingCompetitorAnalysisDialog.tsx
diff --git a/auto-claude-ui/src/renderer/components/FileAutocomplete.tsx b/apps/frontend/src/renderer/components/FileAutocomplete.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/FileAutocomplete.tsx
rename to apps/frontend/src/renderer/components/FileAutocomplete.tsx
diff --git a/auto-claude-ui/src/renderer/components/FileExplorerPanel.tsx b/apps/frontend/src/renderer/components/FileExplorerPanel.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/FileExplorerPanel.tsx
rename to apps/frontend/src/renderer/components/FileExplorerPanel.tsx
diff --git a/auto-claude-ui/src/renderer/components/FileTree.tsx b/apps/frontend/src/renderer/components/FileTree.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/FileTree.tsx
rename to apps/frontend/src/renderer/components/FileTree.tsx
diff --git a/auto-claude-ui/src/renderer/components/FileTreeItem.tsx b/apps/frontend/src/renderer/components/FileTreeItem.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/FileTreeItem.tsx
rename to apps/frontend/src/renderer/components/FileTreeItem.tsx
diff --git a/auto-claude-ui/src/renderer/components/GitHubIssues.tsx b/apps/frontend/src/renderer/components/GitHubIssues.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/GitHubIssues.tsx
rename to apps/frontend/src/renderer/components/GitHubIssues.tsx
diff --git a/auto-claude-ui/src/renderer/components/GitHubSetupModal.tsx b/apps/frontend/src/renderer/components/GitHubSetupModal.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/GitHubSetupModal.tsx
rename to apps/frontend/src/renderer/components/GitHubSetupModal.tsx
diff --git a/auto-claude-ui/src/renderer/components/GitSetupModal.tsx b/apps/frontend/src/renderer/components/GitSetupModal.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/GitSetupModal.tsx
rename to apps/frontend/src/renderer/components/GitSetupModal.tsx
diff --git a/auto-claude-ui/src/renderer/components/Ideation.tsx b/apps/frontend/src/renderer/components/Ideation.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/Ideation.tsx
rename to apps/frontend/src/renderer/components/Ideation.tsx
diff --git a/auto-claude-ui/src/renderer/components/ImageUpload.tsx b/apps/frontend/src/renderer/components/ImageUpload.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ImageUpload.tsx
rename to apps/frontend/src/renderer/components/ImageUpload.tsx
diff --git a/auto-claude-ui/src/renderer/components/Insights.tsx b/apps/frontend/src/renderer/components/Insights.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/Insights.tsx
rename to apps/frontend/src/renderer/components/Insights.tsx
diff --git a/auto-claude-ui/src/renderer/components/InsightsModelSelector.tsx b/apps/frontend/src/renderer/components/InsightsModelSelector.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/InsightsModelSelector.tsx
rename to apps/frontend/src/renderer/components/InsightsModelSelector.tsx
diff --git a/auto-claude-ui/src/renderer/components/KanbanBoard.tsx b/apps/frontend/src/renderer/components/KanbanBoard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/KanbanBoard.tsx
rename to apps/frontend/src/renderer/components/KanbanBoard.tsx
diff --git a/auto-claude-ui/src/renderer/components/LinearTaskImportModal.tsx b/apps/frontend/src/renderer/components/LinearTaskImportModal.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/LinearTaskImportModal.tsx
rename to apps/frontend/src/renderer/components/LinearTaskImportModal.tsx
diff --git a/auto-claude-ui/src/renderer/components/PhaseProgressIndicator.tsx b/apps/frontend/src/renderer/components/PhaseProgressIndicator.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/PhaseProgressIndicator.tsx
rename to apps/frontend/src/renderer/components/PhaseProgressIndicator.tsx
diff --git a/auto-claude-ui/src/renderer/components/ProactiveSwapListener.tsx b/apps/frontend/src/renderer/components/ProactiveSwapListener.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ProactiveSwapListener.tsx
rename to apps/frontend/src/renderer/components/ProactiveSwapListener.tsx
diff --git a/auto-claude-ui/src/renderer/components/ProjectSettings.tsx b/apps/frontend/src/renderer/components/ProjectSettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ProjectSettings.tsx
rename to apps/frontend/src/renderer/components/ProjectSettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/ProjectTabBar.tsx b/apps/frontend/src/renderer/components/ProjectTabBar.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ProjectTabBar.tsx
rename to apps/frontend/src/renderer/components/ProjectTabBar.tsx
diff --git a/auto-claude-ui/src/renderer/components/RateLimitIndicator.tsx b/apps/frontend/src/renderer/components/RateLimitIndicator.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/RateLimitIndicator.tsx
rename to apps/frontend/src/renderer/components/RateLimitIndicator.tsx
diff --git a/auto-claude-ui/src/renderer/components/RateLimitModal.tsx b/apps/frontend/src/renderer/components/RateLimitModal.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/RateLimitModal.tsx
rename to apps/frontend/src/renderer/components/RateLimitModal.tsx
diff --git a/auto-claude-ui/src/renderer/components/ReferencedFilesSection.tsx b/apps/frontend/src/renderer/components/ReferencedFilesSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ReferencedFilesSection.tsx
rename to apps/frontend/src/renderer/components/ReferencedFilesSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/Roadmap.tsx b/apps/frontend/src/renderer/components/Roadmap.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/Roadmap.tsx
rename to apps/frontend/src/renderer/components/Roadmap.tsx
diff --git a/auto-claude-ui/src/renderer/components/RoadmapGenerationProgress.tsx b/apps/frontend/src/renderer/components/RoadmapGenerationProgress.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/RoadmapGenerationProgress.tsx
rename to apps/frontend/src/renderer/components/RoadmapGenerationProgress.tsx
diff --git a/auto-claude-ui/src/renderer/components/RoadmapKanbanView.tsx b/apps/frontend/src/renderer/components/RoadmapKanbanView.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/RoadmapKanbanView.tsx
rename to apps/frontend/src/renderer/components/RoadmapKanbanView.tsx
diff --git a/auto-claude-ui/src/renderer/components/SDKRateLimitModal.tsx b/apps/frontend/src/renderer/components/SDKRateLimitModal.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/SDKRateLimitModal.tsx
rename to apps/frontend/src/renderer/components/SDKRateLimitModal.tsx
diff --git a/auto-claude-ui/src/renderer/components/Sidebar.tsx b/apps/frontend/src/renderer/components/Sidebar.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/Sidebar.tsx
rename to apps/frontend/src/renderer/components/Sidebar.tsx
diff --git a/auto-claude-ui/src/renderer/components/SortableFeatureCard.tsx b/apps/frontend/src/renderer/components/SortableFeatureCard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/SortableFeatureCard.tsx
rename to apps/frontend/src/renderer/components/SortableFeatureCard.tsx
diff --git a/auto-claude-ui/src/renderer/components/SortableProjectTab.tsx b/apps/frontend/src/renderer/components/SortableProjectTab.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/SortableProjectTab.tsx
rename to apps/frontend/src/renderer/components/SortableProjectTab.tsx
diff --git a/auto-claude-ui/src/renderer/components/SortableTaskCard.tsx b/apps/frontend/src/renderer/components/SortableTaskCard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/SortableTaskCard.tsx
rename to apps/frontend/src/renderer/components/SortableTaskCard.tsx
diff --git a/auto-claude-ui/src/renderer/components/TaskCard.tsx b/apps/frontend/src/renderer/components/TaskCard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/TaskCard.tsx
rename to apps/frontend/src/renderer/components/TaskCard.tsx
diff --git a/auto-claude-ui/src/renderer/components/TaskCreationWizard.tsx b/apps/frontend/src/renderer/components/TaskCreationWizard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/TaskCreationWizard.tsx
rename to apps/frontend/src/renderer/components/TaskCreationWizard.tsx
diff --git a/auto-claude-ui/src/renderer/components/TaskDetailPanel.tsx b/apps/frontend/src/renderer/components/TaskDetailPanel.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/TaskDetailPanel.tsx
rename to apps/frontend/src/renderer/components/TaskDetailPanel.tsx
diff --git a/auto-claude-ui/src/renderer/components/TaskEditDialog.tsx b/apps/frontend/src/renderer/components/TaskEditDialog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/TaskEditDialog.tsx
rename to apps/frontend/src/renderer/components/TaskEditDialog.tsx
diff --git a/auto-claude-ui/src/renderer/components/TaskFileExplorerDrawer.tsx b/apps/frontend/src/renderer/components/TaskFileExplorerDrawer.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/TaskFileExplorerDrawer.tsx
rename to apps/frontend/src/renderer/components/TaskFileExplorerDrawer.tsx
diff --git a/auto-claude-ui/src/renderer/components/Terminal.tsx b/apps/frontend/src/renderer/components/Terminal.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/Terminal.tsx
rename to apps/frontend/src/renderer/components/Terminal.tsx
diff --git a/auto-claude-ui/src/renderer/components/TerminalGrid.tsx b/apps/frontend/src/renderer/components/TerminalGrid.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/TerminalGrid.tsx
rename to apps/frontend/src/renderer/components/TerminalGrid.tsx
diff --git a/auto-claude-ui/src/renderer/components/UsageIndicator.tsx b/apps/frontend/src/renderer/components/UsageIndicator.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/UsageIndicator.tsx
rename to apps/frontend/src/renderer/components/UsageIndicator.tsx
diff --git a/auto-claude-ui/src/renderer/components/WelcomeScreen.tsx b/apps/frontend/src/renderer/components/WelcomeScreen.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/WelcomeScreen.tsx
rename to apps/frontend/src/renderer/components/WelcomeScreen.tsx
diff --git a/auto-claude-ui/src/renderer/components/Worktrees.tsx b/apps/frontend/src/renderer/components/Worktrees.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/Worktrees.tsx
rename to apps/frontend/src/renderer/components/Worktrees.tsx
diff --git a/auto-claude-ui/src/renderer/components/__tests__/ProjectTabBar.test.tsx b/apps/frontend/src/renderer/components/__tests__/ProjectTabBar.test.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/__tests__/ProjectTabBar.test.tsx
rename to apps/frontend/src/renderer/components/__tests__/ProjectTabBar.test.tsx
diff --git a/auto-claude-ui/src/renderer/components/__tests__/RoadmapGenerationProgress.test.tsx b/apps/frontend/src/renderer/components/__tests__/RoadmapGenerationProgress.test.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/__tests__/RoadmapGenerationProgress.test.tsx
rename to apps/frontend/src/renderer/components/__tests__/RoadmapGenerationProgress.test.tsx
diff --git a/auto-claude-ui/src/renderer/components/changelog/ArchiveTasksCard.tsx b/apps/frontend/src/renderer/components/changelog/ArchiveTasksCard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/ArchiveTasksCard.tsx
rename to apps/frontend/src/renderer/components/changelog/ArchiveTasksCard.tsx
diff --git a/auto-claude-ui/src/renderer/components/changelog/Changelog.tsx b/apps/frontend/src/renderer/components/changelog/Changelog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/Changelog.tsx
rename to apps/frontend/src/renderer/components/changelog/Changelog.tsx
diff --git a/auto-claude-ui/src/renderer/components/changelog/ChangelogDetails.tsx b/apps/frontend/src/renderer/components/changelog/ChangelogDetails.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/ChangelogDetails.tsx
rename to apps/frontend/src/renderer/components/changelog/ChangelogDetails.tsx
diff --git a/auto-claude-ui/src/renderer/components/changelog/ChangelogEntry.tsx b/apps/frontend/src/renderer/components/changelog/ChangelogEntry.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/ChangelogEntry.tsx
rename to apps/frontend/src/renderer/components/changelog/ChangelogEntry.tsx
diff --git a/auto-claude-ui/src/renderer/components/changelog/ChangelogFilters.tsx b/apps/frontend/src/renderer/components/changelog/ChangelogFilters.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/ChangelogFilters.tsx
rename to apps/frontend/src/renderer/components/changelog/ChangelogFilters.tsx
diff --git a/auto-claude-ui/src/renderer/components/changelog/ChangelogHeader.tsx b/apps/frontend/src/renderer/components/changelog/ChangelogHeader.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/ChangelogHeader.tsx
rename to apps/frontend/src/renderer/components/changelog/ChangelogHeader.tsx
diff --git a/auto-claude-ui/src/renderer/components/changelog/ChangelogList.tsx b/apps/frontend/src/renderer/components/changelog/ChangelogList.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/ChangelogList.tsx
rename to apps/frontend/src/renderer/components/changelog/ChangelogList.tsx
diff --git a/auto-claude-ui/src/renderer/components/changelog/ConfigurationPanel.tsx b/apps/frontend/src/renderer/components/changelog/ConfigurationPanel.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/ConfigurationPanel.tsx
rename to apps/frontend/src/renderer/components/changelog/ConfigurationPanel.tsx
diff --git a/auto-claude-ui/src/renderer/components/changelog/GitHubReleaseCard.tsx b/apps/frontend/src/renderer/components/changelog/GitHubReleaseCard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/GitHubReleaseCard.tsx
rename to apps/frontend/src/renderer/components/changelog/GitHubReleaseCard.tsx
diff --git a/auto-claude-ui/src/renderer/components/changelog/PreviewPanel.tsx b/apps/frontend/src/renderer/components/changelog/PreviewPanel.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/PreviewPanel.tsx
rename to apps/frontend/src/renderer/components/changelog/PreviewPanel.tsx
diff --git a/auto-claude-ui/src/renderer/components/changelog/REFACTORING_SUMMARY.md b/apps/frontend/src/renderer/components/changelog/REFACTORING_SUMMARY.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/REFACTORING_SUMMARY.md
rename to apps/frontend/src/renderer/components/changelog/REFACTORING_SUMMARY.md
diff --git a/auto-claude-ui/src/renderer/components/changelog/Step3SuccessScreen.tsx b/apps/frontend/src/renderer/components/changelog/Step3SuccessScreen.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/Step3SuccessScreen.tsx
rename to apps/frontend/src/renderer/components/changelog/Step3SuccessScreen.tsx
diff --git a/auto-claude-ui/src/renderer/components/changelog/hooks/useChangelog.ts b/apps/frontend/src/renderer/components/changelog/hooks/useChangelog.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/hooks/useChangelog.ts
rename to apps/frontend/src/renderer/components/changelog/hooks/useChangelog.ts
diff --git a/auto-claude-ui/src/renderer/components/changelog/hooks/useImageUpload.ts b/apps/frontend/src/renderer/components/changelog/hooks/useImageUpload.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/hooks/useImageUpload.ts
rename to apps/frontend/src/renderer/components/changelog/hooks/useImageUpload.ts
diff --git a/auto-claude-ui/src/renderer/components/changelog/index.ts b/apps/frontend/src/renderer/components/changelog/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/index.ts
rename to apps/frontend/src/renderer/components/changelog/index.ts
diff --git a/auto-claude-ui/src/renderer/components/changelog/utils.ts b/apps/frontend/src/renderer/components/changelog/utils.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/changelog/utils.ts
rename to apps/frontend/src/renderer/components/changelog/utils.ts
diff --git a/auto-claude-ui/src/renderer/components/context/Context.tsx b/apps/frontend/src/renderer/components/context/Context.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/Context.tsx
rename to apps/frontend/src/renderer/components/context/Context.tsx
diff --git a/auto-claude-ui/src/renderer/components/context/InfoItem.tsx b/apps/frontend/src/renderer/components/context/InfoItem.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/InfoItem.tsx
rename to apps/frontend/src/renderer/components/context/InfoItem.tsx
diff --git a/auto-claude-ui/src/renderer/components/context/MemoriesTab.tsx b/apps/frontend/src/renderer/components/context/MemoriesTab.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/MemoriesTab.tsx
rename to apps/frontend/src/renderer/components/context/MemoriesTab.tsx
diff --git a/auto-claude-ui/src/renderer/components/context/MemoryCard.tsx b/apps/frontend/src/renderer/components/context/MemoryCard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/MemoryCard.tsx
rename to apps/frontend/src/renderer/components/context/MemoryCard.tsx
diff --git a/auto-claude-ui/src/renderer/components/context/ProjectIndexTab.tsx b/apps/frontend/src/renderer/components/context/ProjectIndexTab.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/ProjectIndexTab.tsx
rename to apps/frontend/src/renderer/components/context/ProjectIndexTab.tsx
diff --git a/auto-claude-ui/src/renderer/components/context/README.md b/apps/frontend/src/renderer/components/context/README.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/README.md
rename to apps/frontend/src/renderer/components/context/README.md
diff --git a/auto-claude-ui/src/renderer/components/context/ServiceCard.tsx b/apps/frontend/src/renderer/components/context/ServiceCard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/ServiceCard.tsx
rename to apps/frontend/src/renderer/components/context/ServiceCard.tsx
diff --git a/auto-claude-ui/src/renderer/components/context/constants.ts b/apps/frontend/src/renderer/components/context/constants.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/constants.ts
rename to apps/frontend/src/renderer/components/context/constants.ts
diff --git a/auto-claude-ui/src/renderer/components/context/hooks.ts b/apps/frontend/src/renderer/components/context/hooks.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/hooks.ts
rename to apps/frontend/src/renderer/components/context/hooks.ts
diff --git a/auto-claude-ui/src/renderer/components/context/index.ts b/apps/frontend/src/renderer/components/context/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/index.ts
rename to apps/frontend/src/renderer/components/context/index.ts
diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/APIRoutesSection.tsx b/apps/frontend/src/renderer/components/context/service-sections/APIRoutesSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/service-sections/APIRoutesSection.tsx
rename to apps/frontend/src/renderer/components/context/service-sections/APIRoutesSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/DatabaseSection.tsx b/apps/frontend/src/renderer/components/context/service-sections/DatabaseSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/service-sections/DatabaseSection.tsx
rename to apps/frontend/src/renderer/components/context/service-sections/DatabaseSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/DependenciesSection.tsx b/apps/frontend/src/renderer/components/context/service-sections/DependenciesSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/service-sections/DependenciesSection.tsx
rename to apps/frontend/src/renderer/components/context/service-sections/DependenciesSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/EnvironmentSection.tsx b/apps/frontend/src/renderer/components/context/service-sections/EnvironmentSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/service-sections/EnvironmentSection.tsx
rename to apps/frontend/src/renderer/components/context/service-sections/EnvironmentSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/ExternalServicesSection.tsx b/apps/frontend/src/renderer/components/context/service-sections/ExternalServicesSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/service-sections/ExternalServicesSection.tsx
rename to apps/frontend/src/renderer/components/context/service-sections/ExternalServicesSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/MonitoringSection.tsx b/apps/frontend/src/renderer/components/context/service-sections/MonitoringSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/service-sections/MonitoringSection.tsx
rename to apps/frontend/src/renderer/components/context/service-sections/MonitoringSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/index.ts b/apps/frontend/src/renderer/components/context/service-sections/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/service-sections/index.ts
rename to apps/frontend/src/renderer/components/context/service-sections/index.ts
diff --git a/auto-claude-ui/src/renderer/components/context/types.ts b/apps/frontend/src/renderer/components/context/types.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/types.ts
rename to apps/frontend/src/renderer/components/context/types.ts
diff --git a/auto-claude-ui/src/renderer/components/context/utils.ts b/apps/frontend/src/renderer/components/context/utils.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/context/utils.ts
rename to apps/frontend/src/renderer/components/context/utils.ts
diff --git a/auto-claude-ui/src/renderer/components/github-issues/ARCHITECTURE.md b/apps/frontend/src/renderer/components/github-issues/ARCHITECTURE.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/ARCHITECTURE.md
rename to apps/frontend/src/renderer/components/github-issues/ARCHITECTURE.md
diff --git a/auto-claude-ui/src/renderer/components/github-issues/README.md b/apps/frontend/src/renderer/components/github-issues/README.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/README.md
rename to apps/frontend/src/renderer/components/github-issues/README.md
diff --git a/auto-claude-ui/src/renderer/components/github-issues/REFACTORING_SUMMARY.md b/apps/frontend/src/renderer/components/github-issues/REFACTORING_SUMMARY.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/REFACTORING_SUMMARY.md
rename to apps/frontend/src/renderer/components/github-issues/REFACTORING_SUMMARY.md
diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/EmptyStates.tsx b/apps/frontend/src/renderer/components/github-issues/components/EmptyStates.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/components/EmptyStates.tsx
rename to apps/frontend/src/renderer/components/github-issues/components/EmptyStates.tsx
diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/InvestigationDialog.tsx b/apps/frontend/src/renderer/components/github-issues/components/InvestigationDialog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/components/InvestigationDialog.tsx
rename to apps/frontend/src/renderer/components/github-issues/components/InvestigationDialog.tsx
diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/IssueDetail.tsx b/apps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/components/IssueDetail.tsx
rename to apps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsx
diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/IssueList.tsx b/apps/frontend/src/renderer/components/github-issues/components/IssueList.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/components/IssueList.tsx
rename to apps/frontend/src/renderer/components/github-issues/components/IssueList.tsx
diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/IssueListHeader.tsx b/apps/frontend/src/renderer/components/github-issues/components/IssueListHeader.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/components/IssueListHeader.tsx
rename to apps/frontend/src/renderer/components/github-issues/components/IssueListHeader.tsx
diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/IssueListItem.tsx b/apps/frontend/src/renderer/components/github-issues/components/IssueListItem.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/components/IssueListItem.tsx
rename to apps/frontend/src/renderer/components/github-issues/components/IssueListItem.tsx
diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/index.ts b/apps/frontend/src/renderer/components/github-issues/components/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/components/index.ts
rename to apps/frontend/src/renderer/components/github-issues/components/index.ts
diff --git a/auto-claude-ui/src/renderer/components/github-issues/hooks/index.ts b/apps/frontend/src/renderer/components/github-issues/hooks/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/hooks/index.ts
rename to apps/frontend/src/renderer/components/github-issues/hooks/index.ts
diff --git a/auto-claude-ui/src/renderer/components/github-issues/hooks/useGitHubInvestigation.ts b/apps/frontend/src/renderer/components/github-issues/hooks/useGitHubInvestigation.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/hooks/useGitHubInvestigation.ts
rename to apps/frontend/src/renderer/components/github-issues/hooks/useGitHubInvestigation.ts
diff --git a/auto-claude-ui/src/renderer/components/github-issues/hooks/useGitHubIssues.ts b/apps/frontend/src/renderer/components/github-issues/hooks/useGitHubIssues.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/hooks/useGitHubIssues.ts
rename to apps/frontend/src/renderer/components/github-issues/hooks/useGitHubIssues.ts
diff --git a/auto-claude-ui/src/renderer/components/github-issues/hooks/useIssueFiltering.ts b/apps/frontend/src/renderer/components/github-issues/hooks/useIssueFiltering.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/hooks/useIssueFiltering.ts
rename to apps/frontend/src/renderer/components/github-issues/hooks/useIssueFiltering.ts
diff --git a/auto-claude-ui/src/renderer/components/github-issues/index.ts b/apps/frontend/src/renderer/components/github-issues/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/index.ts
rename to apps/frontend/src/renderer/components/github-issues/index.ts
diff --git a/auto-claude-ui/src/renderer/components/github-issues/types/index.ts b/apps/frontend/src/renderer/components/github-issues/types/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/types/index.ts
rename to apps/frontend/src/renderer/components/github-issues/types/index.ts
diff --git a/auto-claude-ui/src/renderer/components/github-issues/utils/index.ts b/apps/frontend/src/renderer/components/github-issues/utils/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/github-issues/utils/index.ts
rename to apps/frontend/src/renderer/components/github-issues/utils/index.ts
diff --git a/auto-claude-ui/src/renderer/components/ideation/GenerationProgressScreen.tsx b/apps/frontend/src/renderer/components/ideation/GenerationProgressScreen.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/GenerationProgressScreen.tsx
rename to apps/frontend/src/renderer/components/ideation/GenerationProgressScreen.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeaCard.tsx b/apps/frontend/src/renderer/components/ideation/IdeaCard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/IdeaCard.tsx
rename to apps/frontend/src/renderer/components/ideation/IdeaCard.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeaDetailPanel.tsx b/apps/frontend/src/renderer/components/ideation/IdeaDetailPanel.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/IdeaDetailPanel.tsx
rename to apps/frontend/src/renderer/components/ideation/IdeaDetailPanel.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeaSkeletonCard.tsx b/apps/frontend/src/renderer/components/ideation/IdeaSkeletonCard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/IdeaSkeletonCard.tsx
rename to apps/frontend/src/renderer/components/ideation/IdeaSkeletonCard.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/Ideation.tsx b/apps/frontend/src/renderer/components/ideation/Ideation.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/Ideation.tsx
rename to apps/frontend/src/renderer/components/ideation/Ideation.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeationDialogs.tsx b/apps/frontend/src/renderer/components/ideation/IdeationDialogs.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/IdeationDialogs.tsx
rename to apps/frontend/src/renderer/components/ideation/IdeationDialogs.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeationEmptyState.tsx b/apps/frontend/src/renderer/components/ideation/IdeationEmptyState.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/IdeationEmptyState.tsx
rename to apps/frontend/src/renderer/components/ideation/IdeationEmptyState.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeationFilters.tsx b/apps/frontend/src/renderer/components/ideation/IdeationFilters.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/IdeationFilters.tsx
rename to apps/frontend/src/renderer/components/ideation/IdeationFilters.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeationHeader.tsx b/apps/frontend/src/renderer/components/ideation/IdeationHeader.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/IdeationHeader.tsx
rename to apps/frontend/src/renderer/components/ideation/IdeationHeader.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/TypeIcon.tsx b/apps/frontend/src/renderer/components/ideation/TypeIcon.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/TypeIcon.tsx
rename to apps/frontend/src/renderer/components/ideation/TypeIcon.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/TypeStateIcon.tsx b/apps/frontend/src/renderer/components/ideation/TypeStateIcon.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/TypeStateIcon.tsx
rename to apps/frontend/src/renderer/components/ideation/TypeStateIcon.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/constants.ts b/apps/frontend/src/renderer/components/ideation/constants.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/constants.ts
rename to apps/frontend/src/renderer/components/ideation/constants.ts
diff --git a/auto-claude-ui/src/renderer/components/ideation/details/CodeImprovementDetails.tsx b/apps/frontend/src/renderer/components/ideation/details/CodeImprovementDetails.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/details/CodeImprovementDetails.tsx
rename to apps/frontend/src/renderer/components/ideation/details/CodeImprovementDetails.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/details/CodeQualityDetails.tsx b/apps/frontend/src/renderer/components/ideation/details/CodeQualityDetails.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/details/CodeQualityDetails.tsx
rename to apps/frontend/src/renderer/components/ideation/details/CodeQualityDetails.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/details/DocumentationGapDetails.tsx b/apps/frontend/src/renderer/components/ideation/details/DocumentationGapDetails.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/details/DocumentationGapDetails.tsx
rename to apps/frontend/src/renderer/components/ideation/details/DocumentationGapDetails.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/details/PerformanceOptimizationDetails.tsx b/apps/frontend/src/renderer/components/ideation/details/PerformanceOptimizationDetails.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/details/PerformanceOptimizationDetails.tsx
rename to apps/frontend/src/renderer/components/ideation/details/PerformanceOptimizationDetails.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/details/SecurityHardeningDetails.tsx b/apps/frontend/src/renderer/components/ideation/details/SecurityHardeningDetails.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/details/SecurityHardeningDetails.tsx
rename to apps/frontend/src/renderer/components/ideation/details/SecurityHardeningDetails.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/details/UIUXDetails.tsx b/apps/frontend/src/renderer/components/ideation/details/UIUXDetails.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/details/UIUXDetails.tsx
rename to apps/frontend/src/renderer/components/ideation/details/UIUXDetails.tsx
diff --git a/auto-claude-ui/src/renderer/components/ideation/hooks/useIdeation.ts b/apps/frontend/src/renderer/components/ideation/hooks/useIdeation.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/hooks/useIdeation.ts
rename to apps/frontend/src/renderer/components/ideation/hooks/useIdeation.ts
diff --git a/auto-claude-ui/src/renderer/components/ideation/index.ts b/apps/frontend/src/renderer/components/ideation/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/index.ts
rename to apps/frontend/src/renderer/components/ideation/index.ts
diff --git a/auto-claude-ui/src/renderer/components/ideation/type-guards.ts b/apps/frontend/src/renderer/components/ideation/type-guards.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ideation/type-guards.ts
rename to apps/frontend/src/renderer/components/ideation/type-guards.ts
diff --git a/auto-claude-ui/src/renderer/components/index.ts b/apps/frontend/src/renderer/components/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/index.ts
rename to apps/frontend/src/renderer/components/index.ts
diff --git a/auto-claude-ui/src/renderer/components/linear-import/LinearTaskImportModalRefactored.tsx b/apps/frontend/src/renderer/components/linear-import/LinearTaskImportModalRefactored.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/LinearTaskImportModalRefactored.tsx
rename to apps/frontend/src/renderer/components/linear-import/LinearTaskImportModalRefactored.tsx
diff --git a/auto-claude-ui/src/renderer/components/linear-import/README.md b/apps/frontend/src/renderer/components/linear-import/README.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/README.md
rename to apps/frontend/src/renderer/components/linear-import/README.md
diff --git a/auto-claude-ui/src/renderer/components/linear-import/REFACTORING_SUMMARY.md b/apps/frontend/src/renderer/components/linear-import/REFACTORING_SUMMARY.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/REFACTORING_SUMMARY.md
rename to apps/frontend/src/renderer/components/linear-import/REFACTORING_SUMMARY.md
diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/ErrorBanner.tsx b/apps/frontend/src/renderer/components/linear-import/components/ErrorBanner.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/components/ErrorBanner.tsx
rename to apps/frontend/src/renderer/components/linear-import/components/ErrorBanner.tsx
diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/ImportSuccessBanner.tsx b/apps/frontend/src/renderer/components/linear-import/components/ImportSuccessBanner.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/components/ImportSuccessBanner.tsx
rename to apps/frontend/src/renderer/components/linear-import/components/ImportSuccessBanner.tsx
diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/IssueCard.tsx b/apps/frontend/src/renderer/components/linear-import/components/IssueCard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/components/IssueCard.tsx
rename to apps/frontend/src/renderer/components/linear-import/components/IssueCard.tsx
diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/IssueList.tsx b/apps/frontend/src/renderer/components/linear-import/components/IssueList.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/components/IssueList.tsx
rename to apps/frontend/src/renderer/components/linear-import/components/IssueList.tsx
diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/SearchAndFilterBar.tsx b/apps/frontend/src/renderer/components/linear-import/components/SearchAndFilterBar.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/components/SearchAndFilterBar.tsx
rename to apps/frontend/src/renderer/components/linear-import/components/SearchAndFilterBar.tsx
diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/SelectionControls.tsx b/apps/frontend/src/renderer/components/linear-import/components/SelectionControls.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/components/SelectionControls.tsx
rename to apps/frontend/src/renderer/components/linear-import/components/SelectionControls.tsx
diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/TeamProjectSelector.tsx b/apps/frontend/src/renderer/components/linear-import/components/TeamProjectSelector.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/components/TeamProjectSelector.tsx
rename to apps/frontend/src/renderer/components/linear-import/components/TeamProjectSelector.tsx
diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/index.ts b/apps/frontend/src/renderer/components/linear-import/components/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/components/index.ts
rename to apps/frontend/src/renderer/components/linear-import/components/index.ts
diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/index.ts b/apps/frontend/src/renderer/components/linear-import/hooks/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/hooks/index.ts
rename to apps/frontend/src/renderer/components/linear-import/hooks/index.ts
diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useIssueFiltering.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useIssueFiltering.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useIssueFiltering.ts
rename to apps/frontend/src/renderer/components/linear-import/hooks/useIssueFiltering.ts
diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useIssueSelection.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useIssueSelection.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useIssueSelection.ts
rename to apps/frontend/src/renderer/components/linear-import/hooks/useIssueSelection.ts
diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearImport.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useLinearImport.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearImport.ts
rename to apps/frontend/src/renderer/components/linear-import/hooks/useLinearImport.ts
diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearImportModal.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useLinearImportModal.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearImportModal.ts
rename to apps/frontend/src/renderer/components/linear-import/hooks/useLinearImportModal.ts
diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearIssues.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useLinearIssues.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearIssues.ts
rename to apps/frontend/src/renderer/components/linear-import/hooks/useLinearIssues.ts
diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearProjects.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useLinearProjects.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearProjects.ts
rename to apps/frontend/src/renderer/components/linear-import/hooks/useLinearProjects.ts
diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearTeams.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useLinearTeams.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearTeams.ts
rename to apps/frontend/src/renderer/components/linear-import/hooks/useLinearTeams.ts
diff --git a/auto-claude-ui/src/renderer/components/linear-import/index.ts b/apps/frontend/src/renderer/components/linear-import/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/index.ts
rename to apps/frontend/src/renderer/components/linear-import/index.ts
diff --git a/auto-claude-ui/src/renderer/components/linear-import/types.ts b/apps/frontend/src/renderer/components/linear-import/types.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/linear-import/types.ts
rename to apps/frontend/src/renderer/components/linear-import/types.ts
diff --git a/auto-claude-ui/src/renderer/components/onboarding/CompletionStep.tsx b/apps/frontend/src/renderer/components/onboarding/CompletionStep.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/onboarding/CompletionStep.tsx
rename to apps/frontend/src/renderer/components/onboarding/CompletionStep.tsx
diff --git a/auto-claude-ui/src/renderer/components/onboarding/FirstSpecStep.tsx b/apps/frontend/src/renderer/components/onboarding/FirstSpecStep.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/onboarding/FirstSpecStep.tsx
rename to apps/frontend/src/renderer/components/onboarding/FirstSpecStep.tsx
diff --git a/auto-claude-ui/src/renderer/components/onboarding/GraphitiStep.tsx b/apps/frontend/src/renderer/components/onboarding/GraphitiStep.tsx
similarity index 99%
rename from auto-claude-ui/src/renderer/components/onboarding/GraphitiStep.tsx
rename to apps/frontend/src/renderer/components/onboarding/GraphitiStep.tsx
index 7dbea07d..d72d485c 100644
--- a/auto-claude-ui/src/renderer/components/onboarding/GraphitiStep.tsx
+++ b/apps/frontend/src/renderer/components/onboarding/GraphitiStep.tsx
@@ -99,8 +99,7 @@ interface ValidationStatus {
/**
* Graphiti memory configuration step for the onboarding wizard.
* Uses LadybugDB (embedded database) - no Docker required.
- * Allows users to optionally configure Graphiti memory backend with multiple provider options.
- * This step is entirely optional and can be skipped.
+ * Allows users to configure Graphiti memory backend with multiple provider options.
*/
export function GraphitiStep({ onNext, onBack, onSkip }: GraphitiStepProps) {
const { settings, updateSettings } = useSettingsStore();
@@ -688,7 +687,7 @@ export function GraphitiStep({ onNext, onBack, onSkip }: GraphitiStepProps) {
- Memory & Context (Optional)
+ Memory & Context
Enable Graphiti for persistent memory across coding sessions
diff --git a/auto-claude-ui/src/renderer/components/onboarding/MemoryStep.tsx b/apps/frontend/src/renderer/components/onboarding/MemoryStep.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/onboarding/MemoryStep.tsx
rename to apps/frontend/src/renderer/components/onboarding/MemoryStep.tsx
diff --git a/auto-claude-ui/src/renderer/components/onboarding/OAuthStep.tsx b/apps/frontend/src/renderer/components/onboarding/OAuthStep.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/onboarding/OAuthStep.tsx
rename to apps/frontend/src/renderer/components/onboarding/OAuthStep.tsx
diff --git a/auto-claude-ui/src/renderer/components/onboarding/OllamaModelSelector.tsx b/apps/frontend/src/renderer/components/onboarding/OllamaModelSelector.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/onboarding/OllamaModelSelector.tsx
rename to apps/frontend/src/renderer/components/onboarding/OllamaModelSelector.tsx
diff --git a/auto-claude-ui/src/renderer/components/onboarding/OnboardingWizard.tsx b/apps/frontend/src/renderer/components/onboarding/OnboardingWizard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/onboarding/OnboardingWizard.tsx
rename to apps/frontend/src/renderer/components/onboarding/OnboardingWizard.tsx
diff --git a/auto-claude-ui/src/renderer/components/onboarding/WelcomeStep.tsx b/apps/frontend/src/renderer/components/onboarding/WelcomeStep.tsx
similarity index 95%
rename from auto-claude-ui/src/renderer/components/onboarding/WelcomeStep.tsx
rename to apps/frontend/src/renderer/components/onboarding/WelcomeStep.tsx
index 1d2e3108..e8744ce5 100644
--- a/auto-claude-ui/src/renderer/components/onboarding/WelcomeStep.tsx
+++ b/apps/frontend/src/renderer/components/onboarding/WelcomeStep.tsx
@@ -50,7 +50,7 @@ export function WelcomeStep({ onGetStarted, onSkip }: WelcomeStepProps) {
{
icon: ,
title: 'Memory & Context',
- description: 'Optional Graphiti integration for persistent memory across sessions'
+ description: 'Persistent memory across sessions with Graphiti'
},
{
icon: ,
@@ -88,7 +88,7 @@ export function WelcomeStep({ onGetStarted, onSkip }: WelcomeStepProps) {
This wizard will help you set up your environment in just a few steps.
- You can configure your Claude OAuth token, optionally set up memory features,
+ You can configure your Claude OAuth token, set up memory features,
and create your first task.
diff --git a/auto-claude-ui/src/renderer/components/onboarding/WizardProgress.tsx b/apps/frontend/src/renderer/components/onboarding/WizardProgress.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/onboarding/WizardProgress.tsx
rename to apps/frontend/src/renderer/components/onboarding/WizardProgress.tsx
diff --git a/auto-claude-ui/src/renderer/components/onboarding/index.ts b/apps/frontend/src/renderer/components/onboarding/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/onboarding/index.ts
rename to apps/frontend/src/renderer/components/onboarding/index.ts
diff --git a/auto-claude-ui/src/renderer/components/project-settings/AgentConfigSection.tsx b/apps/frontend/src/renderer/components/project-settings/AgentConfigSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/AgentConfigSection.tsx
rename to apps/frontend/src/renderer/components/project-settings/AgentConfigSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/AutoBuildIntegration.tsx b/apps/frontend/src/renderer/components/project-settings/AutoBuildIntegration.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/AutoBuildIntegration.tsx
rename to apps/frontend/src/renderer/components/project-settings/AutoBuildIntegration.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/ClaudeAuthSection.tsx b/apps/frontend/src/renderer/components/project-settings/ClaudeAuthSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/ClaudeAuthSection.tsx
rename to apps/frontend/src/renderer/components/project-settings/ClaudeAuthSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/ClaudeOAuthFlow.tsx b/apps/frontend/src/renderer/components/project-settings/ClaudeOAuthFlow.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/ClaudeOAuthFlow.tsx
rename to apps/frontend/src/renderer/components/project-settings/ClaudeOAuthFlow.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/CollapsibleSection.tsx b/apps/frontend/src/renderer/components/project-settings/CollapsibleSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/CollapsibleSection.tsx
rename to apps/frontend/src/renderer/components/project-settings/CollapsibleSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/ConnectionStatus.tsx b/apps/frontend/src/renderer/components/project-settings/ConnectionStatus.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/ConnectionStatus.tsx
rename to apps/frontend/src/renderer/components/project-settings/ConnectionStatus.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/EnvironmentSettings.tsx b/apps/frontend/src/renderer/components/project-settings/EnvironmentSettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/EnvironmentSettings.tsx
rename to apps/frontend/src/renderer/components/project-settings/EnvironmentSettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/GeneralSettings.tsx b/apps/frontend/src/renderer/components/project-settings/GeneralSettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/GeneralSettings.tsx
rename to apps/frontend/src/renderer/components/project-settings/GeneralSettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/GitHubIntegrationSection.tsx b/apps/frontend/src/renderer/components/project-settings/GitHubIntegrationSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/GitHubIntegrationSection.tsx
rename to apps/frontend/src/renderer/components/project-settings/GitHubIntegrationSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/GitHubOAuthFlow.tsx b/apps/frontend/src/renderer/components/project-settings/GitHubOAuthFlow.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/GitHubOAuthFlow.tsx
rename to apps/frontend/src/renderer/components/project-settings/GitHubOAuthFlow.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/InfrastructureStatus.tsx b/apps/frontend/src/renderer/components/project-settings/InfrastructureStatus.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/InfrastructureStatus.tsx
rename to apps/frontend/src/renderer/components/project-settings/InfrastructureStatus.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/IntegrationSettings.tsx b/apps/frontend/src/renderer/components/project-settings/IntegrationSettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/IntegrationSettings.tsx
rename to apps/frontend/src/renderer/components/project-settings/IntegrationSettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/LinearIntegrationSection.tsx b/apps/frontend/src/renderer/components/project-settings/LinearIntegrationSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/LinearIntegrationSection.tsx
rename to apps/frontend/src/renderer/components/project-settings/LinearIntegrationSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/MemoryBackendSection.tsx b/apps/frontend/src/renderer/components/project-settings/MemoryBackendSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/MemoryBackendSection.tsx
rename to apps/frontend/src/renderer/components/project-settings/MemoryBackendSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/NotificationsSection.tsx b/apps/frontend/src/renderer/components/project-settings/NotificationsSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/NotificationsSection.tsx
rename to apps/frontend/src/renderer/components/project-settings/NotificationsSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/PasswordInput.tsx b/apps/frontend/src/renderer/components/project-settings/PasswordInput.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/PasswordInput.tsx
rename to apps/frontend/src/renderer/components/project-settings/PasswordInput.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/ProjectSettings.tsx b/apps/frontend/src/renderer/components/project-settings/ProjectSettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/ProjectSettings.tsx
rename to apps/frontend/src/renderer/components/project-settings/ProjectSettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/README.md b/apps/frontend/src/renderer/components/project-settings/README.md
similarity index 95%
rename from auto-claude-ui/src/renderer/components/project-settings/README.md
rename to apps/frontend/src/renderer/components/project-settings/README.md
index f74c44e5..d7b42c44 100644
--- a/auto-claude-ui/src/renderer/components/project-settings/README.md
+++ b/apps/frontend/src/renderer/components/project-settings/README.md
@@ -33,7 +33,7 @@ project-settings/
├── PasswordInput.tsx # Reusable password input with toggle
├── StatusBadge.tsx # Reusable status badge component
├── ConnectionStatus.tsx # Reusable connection status display
-└── InfrastructureStatus.tsx # Docker/FalkorDB status display
+└── InfrastructureStatus.tsx # LadybugDB memory status display
hooks/
├── index.ts # Barrel export for all hooks
@@ -42,7 +42,7 @@ hooks/
├── useClaudeAuth.ts # Claude authentication status
├── useLinearConnection.ts # Linear connection status
├── useGitHubConnection.ts # GitHub connection status
-└── useInfrastructureStatus.ts # Docker/FalkorDB infrastructure status
+└── useInfrastructureStatus.ts # LadybugDB memory status
```
## Component Breakdown
@@ -125,14 +125,14 @@ hooks/
- `settings`: Project settings
- `onUpdateConfig`: Configuration update handler
- `onUpdateSettings`: Settings update handler
-- `infrastructureStatus`: Docker/FalkorDB status
+- `infrastructureStatus`: LadybugDB memory status
- Infrastructure management handlers
**Responsibilities**:
- Toggle between Graphiti and file-based memory
- Configure LLM and embedding providers
-- Manage FalkorDB connection settings
-- Display infrastructure status (Docker/FalkorDB)
+- Manage LadybugDB connection settings
+- Display infrastructure status (LadybugDB)
- Handle infrastructure startup
#### AgentConfigSection.tsx
@@ -202,7 +202,7 @@ hooks/
**Usage**: Used by Linear and GitHub sections to display connection status.
#### InfrastructureStatus.tsx
-**Purpose**: Displays Docker and FalkorDB status for Graphiti.
+**Purpose**: Displays LadybugDB memory status for Graphiti.
**Props**:
- `infrastructureStatus`: Status object
- `isCheckingInfrastructure`: Loading state
@@ -252,7 +252,7 @@ hooks/
- `isCheckingGitHub`: Loading state
### useInfrastructureStatus.ts
-**Purpose**: Monitors Docker and FalkorDB infrastructure status.
+**Purpose**: Monitors LadybugDB memory infrastructure status.
**Returns**:
- `infrastructureStatus`: Status object
- `isCheckingInfrastructure`: Loading state
diff --git a/auto-claude-ui/src/renderer/components/project-settings/SecuritySettings.tsx b/apps/frontend/src/renderer/components/project-settings/SecuritySettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/SecuritySettings.tsx
rename to apps/frontend/src/renderer/components/project-settings/SecuritySettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/StatusBadge.tsx b/apps/frontend/src/renderer/components/project-settings/StatusBadge.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/StatusBadge.tsx
rename to apps/frontend/src/renderer/components/project-settings/StatusBadge.tsx
diff --git a/auto-claude-ui/src/renderer/components/project-settings/hooks/useProjectSettings.ts b/apps/frontend/src/renderer/components/project-settings/hooks/useProjectSettings.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/hooks/useProjectSettings.ts
rename to apps/frontend/src/renderer/components/project-settings/hooks/useProjectSettings.ts
diff --git a/auto-claude-ui/src/renderer/components/project-settings/index.ts b/apps/frontend/src/renderer/components/project-settings/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/project-settings/index.ts
rename to apps/frontend/src/renderer/components/project-settings/index.ts
diff --git a/auto-claude-ui/src/renderer/components/roadmap/FeatureCard.tsx b/apps/frontend/src/renderer/components/roadmap/FeatureCard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/roadmap/FeatureCard.tsx
rename to apps/frontend/src/renderer/components/roadmap/FeatureCard.tsx
diff --git a/auto-claude-ui/src/renderer/components/roadmap/FeatureDetailPanel.tsx b/apps/frontend/src/renderer/components/roadmap/FeatureDetailPanel.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/roadmap/FeatureDetailPanel.tsx
rename to apps/frontend/src/renderer/components/roadmap/FeatureDetailPanel.tsx
diff --git a/auto-claude-ui/src/renderer/components/roadmap/PhaseCard.tsx b/apps/frontend/src/renderer/components/roadmap/PhaseCard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/roadmap/PhaseCard.tsx
rename to apps/frontend/src/renderer/components/roadmap/PhaseCard.tsx
diff --git a/auto-claude-ui/src/renderer/components/roadmap/README.md b/apps/frontend/src/renderer/components/roadmap/README.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/roadmap/README.md
rename to apps/frontend/src/renderer/components/roadmap/README.md
diff --git a/auto-claude-ui/src/renderer/components/roadmap/RoadmapEmptyState.tsx b/apps/frontend/src/renderer/components/roadmap/RoadmapEmptyState.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/roadmap/RoadmapEmptyState.tsx
rename to apps/frontend/src/renderer/components/roadmap/RoadmapEmptyState.tsx
diff --git a/auto-claude-ui/src/renderer/components/roadmap/RoadmapHeader.tsx b/apps/frontend/src/renderer/components/roadmap/RoadmapHeader.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/roadmap/RoadmapHeader.tsx
rename to apps/frontend/src/renderer/components/roadmap/RoadmapHeader.tsx
diff --git a/auto-claude-ui/src/renderer/components/roadmap/RoadmapTabs.tsx b/apps/frontend/src/renderer/components/roadmap/RoadmapTabs.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/roadmap/RoadmapTabs.tsx
rename to apps/frontend/src/renderer/components/roadmap/RoadmapTabs.tsx
diff --git a/auto-claude-ui/src/renderer/components/roadmap/hooks.ts b/apps/frontend/src/renderer/components/roadmap/hooks.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/roadmap/hooks.ts
rename to apps/frontend/src/renderer/components/roadmap/hooks.ts
diff --git a/auto-claude-ui/src/renderer/components/roadmap/index.ts b/apps/frontend/src/renderer/components/roadmap/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/roadmap/index.ts
rename to apps/frontend/src/renderer/components/roadmap/index.ts
diff --git a/auto-claude-ui/src/renderer/components/roadmap/types.ts b/apps/frontend/src/renderer/components/roadmap/types.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/roadmap/types.ts
rename to apps/frontend/src/renderer/components/roadmap/types.ts
diff --git a/auto-claude-ui/src/renderer/components/roadmap/utils.ts b/apps/frontend/src/renderer/components/roadmap/utils.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/roadmap/utils.ts
rename to apps/frontend/src/renderer/components/roadmap/utils.ts
diff --git a/auto-claude-ui/src/renderer/components/settings/AdvancedSettings.tsx b/apps/frontend/src/renderer/components/settings/AdvancedSettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/AdvancedSettings.tsx
rename to apps/frontend/src/renderer/components/settings/AdvancedSettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/AgentProfileSettings.tsx b/apps/frontend/src/renderer/components/settings/AgentProfileSettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/AgentProfileSettings.tsx
rename to apps/frontend/src/renderer/components/settings/AgentProfileSettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/AppSettings.tsx b/apps/frontend/src/renderer/components/settings/AppSettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/AppSettings.tsx
rename to apps/frontend/src/renderer/components/settings/AppSettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/GeneralSettings.tsx b/apps/frontend/src/renderer/components/settings/GeneralSettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/GeneralSettings.tsx
rename to apps/frontend/src/renderer/components/settings/GeneralSettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/IntegrationSettings.tsx b/apps/frontend/src/renderer/components/settings/IntegrationSettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/IntegrationSettings.tsx
rename to apps/frontend/src/renderer/components/settings/IntegrationSettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/ProjectSelector.tsx b/apps/frontend/src/renderer/components/settings/ProjectSelector.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/ProjectSelector.tsx
rename to apps/frontend/src/renderer/components/settings/ProjectSelector.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/ProjectSettingsContent.tsx b/apps/frontend/src/renderer/components/settings/ProjectSettingsContent.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/ProjectSettingsContent.tsx
rename to apps/frontend/src/renderer/components/settings/ProjectSettingsContent.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/README.md b/apps/frontend/src/renderer/components/settings/README.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/README.md
rename to apps/frontend/src/renderer/components/settings/README.md
diff --git a/auto-claude-ui/src/renderer/components/settings/REFACTORING_SUMMARY.md b/apps/frontend/src/renderer/components/settings/REFACTORING_SUMMARY.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/REFACTORING_SUMMARY.md
rename to apps/frontend/src/renderer/components/settings/REFACTORING_SUMMARY.md
diff --git a/auto-claude-ui/src/renderer/components/settings/SettingsSection.tsx b/apps/frontend/src/renderer/components/settings/SettingsSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/SettingsSection.tsx
rename to apps/frontend/src/renderer/components/settings/SettingsSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/ThemeSelector.tsx b/apps/frontend/src/renderer/components/settings/ThemeSelector.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/ThemeSelector.tsx
rename to apps/frontend/src/renderer/components/settings/ThemeSelector.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/ThemeSettings.tsx b/apps/frontend/src/renderer/components/settings/ThemeSettings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/ThemeSettings.tsx
rename to apps/frontend/src/renderer/components/settings/ThemeSettings.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/common/EmptyProjectState.tsx b/apps/frontend/src/renderer/components/settings/common/EmptyProjectState.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/common/EmptyProjectState.tsx
rename to apps/frontend/src/renderer/components/settings/common/EmptyProjectState.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/common/ErrorDisplay.tsx b/apps/frontend/src/renderer/components/settings/common/ErrorDisplay.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/common/ErrorDisplay.tsx
rename to apps/frontend/src/renderer/components/settings/common/ErrorDisplay.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/common/InitializationGuard.tsx b/apps/frontend/src/renderer/components/settings/common/InitializationGuard.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/common/InitializationGuard.tsx
rename to apps/frontend/src/renderer/components/settings/common/InitializationGuard.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/common/index.ts b/apps/frontend/src/renderer/components/settings/common/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/common/index.ts
rename to apps/frontend/src/renderer/components/settings/common/index.ts
diff --git a/auto-claude-ui/src/renderer/components/settings/hooks/useSettings.ts b/apps/frontend/src/renderer/components/settings/hooks/useSettings.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/hooks/useSettings.ts
rename to apps/frontend/src/renderer/components/settings/hooks/useSettings.ts
diff --git a/auto-claude-ui/src/renderer/components/settings/index.ts b/apps/frontend/src/renderer/components/settings/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/index.ts
rename to apps/frontend/src/renderer/components/settings/index.ts
diff --git a/auto-claude-ui/src/renderer/components/settings/integrations/GitHubIntegration.tsx b/apps/frontend/src/renderer/components/settings/integrations/GitHubIntegration.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/integrations/GitHubIntegration.tsx
rename to apps/frontend/src/renderer/components/settings/integrations/GitHubIntegration.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/integrations/LinearIntegration.tsx b/apps/frontend/src/renderer/components/settings/integrations/LinearIntegration.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/integrations/LinearIntegration.tsx
rename to apps/frontend/src/renderer/components/settings/integrations/LinearIntegration.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/integrations/index.ts b/apps/frontend/src/renderer/components/settings/integrations/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/integrations/index.ts
rename to apps/frontend/src/renderer/components/settings/integrations/index.ts
diff --git a/auto-claude-ui/src/renderer/components/settings/sections/SectionRouter.tsx b/apps/frontend/src/renderer/components/settings/sections/SectionRouter.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/sections/SectionRouter.tsx
rename to apps/frontend/src/renderer/components/settings/sections/SectionRouter.tsx
diff --git a/auto-claude-ui/src/renderer/components/settings/sections/index.ts b/apps/frontend/src/renderer/components/settings/sections/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/sections/index.ts
rename to apps/frontend/src/renderer/components/settings/sections/index.ts
diff --git a/auto-claude-ui/src/renderer/components/settings/utils/hookProxyFactory.ts b/apps/frontend/src/renderer/components/settings/utils/hookProxyFactory.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/utils/hookProxyFactory.ts
rename to apps/frontend/src/renderer/components/settings/utils/hookProxyFactory.ts
diff --git a/auto-claude-ui/src/renderer/components/settings/utils/index.ts b/apps/frontend/src/renderer/components/settings/utils/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/settings/utils/index.ts
rename to apps/frontend/src/renderer/components/settings/utils/index.ts
diff --git a/auto-claude-ui/src/renderer/components/task-detail/README.md b/apps/frontend/src/renderer/components/task-detail/README.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/README.md
rename to apps/frontend/src/renderer/components/task-detail/README.md
diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskActions.tsx b/apps/frontend/src/renderer/components/task-detail/TaskActions.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/TaskActions.tsx
rename to apps/frontend/src/renderer/components/task-detail/TaskActions.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskDetailModal.tsx b/apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/TaskDetailModal.tsx
rename to apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskDetailPanel.tsx b/apps/frontend/src/renderer/components/task-detail/TaskDetailPanel.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/TaskDetailPanel.tsx
rename to apps/frontend/src/renderer/components/task-detail/TaskDetailPanel.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskHeader.tsx b/apps/frontend/src/renderer/components/task-detail/TaskHeader.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/TaskHeader.tsx
rename to apps/frontend/src/renderer/components/task-detail/TaskHeader.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskLogs.tsx b/apps/frontend/src/renderer/components/task-detail/TaskLogs.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/TaskLogs.tsx
rename to apps/frontend/src/renderer/components/task-detail/TaskLogs.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskMetadata.tsx b/apps/frontend/src/renderer/components/task-detail/TaskMetadata.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/TaskMetadata.tsx
rename to apps/frontend/src/renderer/components/task-detail/TaskMetadata.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskProgress.tsx b/apps/frontend/src/renderer/components/task-detail/TaskProgress.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/TaskProgress.tsx
rename to apps/frontend/src/renderer/components/task-detail/TaskProgress.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskReview.tsx b/apps/frontend/src/renderer/components/task-detail/TaskReview.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/TaskReview.tsx
rename to apps/frontend/src/renderer/components/task-detail/TaskReview.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskSubtasks.tsx b/apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/TaskSubtasks.tsx
rename to apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskWarnings.tsx b/apps/frontend/src/renderer/components/task-detail/TaskWarnings.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/TaskWarnings.tsx
rename to apps/frontend/src/renderer/components/task-detail/TaskWarnings.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/hooks/useTaskDetail.ts b/apps/frontend/src/renderer/components/task-detail/hooks/useTaskDetail.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/hooks/useTaskDetail.ts
rename to apps/frontend/src/renderer/components/task-detail/hooks/useTaskDetail.ts
diff --git a/auto-claude-ui/src/renderer/components/task-detail/index.ts b/apps/frontend/src/renderer/components/task-detail/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/index.ts
rename to apps/frontend/src/renderer/components/task-detail/index.ts
diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/ConflictDetailsDialog.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/ConflictDetailsDialog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/task-review/ConflictDetailsDialog.tsx
rename to apps/frontend/src/renderer/components/task-detail/task-review/ConflictDetailsDialog.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/DiffViewDialog.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/DiffViewDialog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/task-review/DiffViewDialog.tsx
rename to apps/frontend/src/renderer/components/task-detail/task-review/DiffViewDialog.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/DiscardDialog.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/DiscardDialog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/task-review/DiscardDialog.tsx
rename to apps/frontend/src/renderer/components/task-detail/task-review/DiscardDialog.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/MergePreviewSummary.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/MergePreviewSummary.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/task-review/MergePreviewSummary.tsx
rename to apps/frontend/src/renderer/components/task-detail/task-review/MergePreviewSummary.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/QAFeedbackSection.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/QAFeedbackSection.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/task-review/QAFeedbackSection.tsx
rename to apps/frontend/src/renderer/components/task-detail/task-review/QAFeedbackSection.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/README.md b/apps/frontend/src/renderer/components/task-detail/task-review/README.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/task-review/README.md
rename to apps/frontend/src/renderer/components/task-detail/task-review/README.md
diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/StagedSuccessMessage.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/StagedSuccessMessage.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/task-review/StagedSuccessMessage.tsx
rename to apps/frontend/src/renderer/components/task-detail/task-review/StagedSuccessMessage.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/WorkspaceMessages.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/WorkspaceMessages.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/task-review/WorkspaceMessages.tsx
rename to apps/frontend/src/renderer/components/task-detail/task-review/WorkspaceMessages.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx
rename to apps/frontend/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx
diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/index.ts b/apps/frontend/src/renderer/components/task-detail/task-review/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/task-review/index.ts
rename to apps/frontend/src/renderer/components/task-detail/task-review/index.ts
diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/utils.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/utils.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/task-detail/task-review/utils.tsx
rename to apps/frontend/src/renderer/components/task-detail/task-review/utils.tsx
diff --git a/auto-claude-ui/src/renderer/components/terminal/README.md b/apps/frontend/src/renderer/components/terminal/README.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/terminal/README.md
rename to apps/frontend/src/renderer/components/terminal/README.md
diff --git a/auto-claude-ui/src/renderer/components/terminal/REFACTORING_SUMMARY.md b/apps/frontend/src/renderer/components/terminal/REFACTORING_SUMMARY.md
similarity index 100%
rename from auto-claude-ui/src/renderer/components/terminal/REFACTORING_SUMMARY.md
rename to apps/frontend/src/renderer/components/terminal/REFACTORING_SUMMARY.md
diff --git a/auto-claude-ui/src/renderer/components/terminal/TaskSelector.tsx b/apps/frontend/src/renderer/components/terminal/TaskSelector.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/terminal/TaskSelector.tsx
rename to apps/frontend/src/renderer/components/terminal/TaskSelector.tsx
diff --git a/auto-claude-ui/src/renderer/components/terminal/TerminalHeader.tsx b/apps/frontend/src/renderer/components/terminal/TerminalHeader.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/terminal/TerminalHeader.tsx
rename to apps/frontend/src/renderer/components/terminal/TerminalHeader.tsx
diff --git a/auto-claude-ui/src/renderer/components/terminal/TerminalTitle.tsx b/apps/frontend/src/renderer/components/terminal/TerminalTitle.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/terminal/TerminalTitle.tsx
rename to apps/frontend/src/renderer/components/terminal/TerminalTitle.tsx
diff --git a/auto-claude-ui/src/renderer/components/terminal/index.ts b/apps/frontend/src/renderer/components/terminal/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/terminal/index.ts
rename to apps/frontend/src/renderer/components/terminal/index.ts
diff --git a/auto-claude-ui/src/renderer/components/terminal/types.ts b/apps/frontend/src/renderer/components/terminal/types.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/terminal/types.ts
rename to apps/frontend/src/renderer/components/terminal/types.ts
diff --git a/auto-claude-ui/src/renderer/components/terminal/useAutoNaming.ts b/apps/frontend/src/renderer/components/terminal/useAutoNaming.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/terminal/useAutoNaming.ts
rename to apps/frontend/src/renderer/components/terminal/useAutoNaming.ts
diff --git a/auto-claude-ui/src/renderer/components/terminal/usePtyProcess.ts b/apps/frontend/src/renderer/components/terminal/usePtyProcess.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/terminal/usePtyProcess.ts
rename to apps/frontend/src/renderer/components/terminal/usePtyProcess.ts
diff --git a/auto-claude-ui/src/renderer/components/terminal/useTerminalEvents.ts b/apps/frontend/src/renderer/components/terminal/useTerminalEvents.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/terminal/useTerminalEvents.ts
rename to apps/frontend/src/renderer/components/terminal/useTerminalEvents.ts
diff --git a/auto-claude-ui/src/renderer/components/terminal/useXterm.ts b/apps/frontend/src/renderer/components/terminal/useXterm.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/terminal/useXterm.ts
rename to apps/frontend/src/renderer/components/terminal/useXterm.ts
diff --git a/auto-claude-ui/src/renderer/components/ui/alert-dialog.tsx b/apps/frontend/src/renderer/components/ui/alert-dialog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/alert-dialog.tsx
rename to apps/frontend/src/renderer/components/ui/alert-dialog.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/badge.tsx b/apps/frontend/src/renderer/components/ui/badge.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/badge.tsx
rename to apps/frontend/src/renderer/components/ui/badge.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/button.tsx b/apps/frontend/src/renderer/components/ui/button.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/button.tsx
rename to apps/frontend/src/renderer/components/ui/button.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/card.tsx b/apps/frontend/src/renderer/components/ui/card.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/card.tsx
rename to apps/frontend/src/renderer/components/ui/card.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/checkbox.tsx b/apps/frontend/src/renderer/components/ui/checkbox.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/checkbox.tsx
rename to apps/frontend/src/renderer/components/ui/checkbox.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/collapsible.tsx b/apps/frontend/src/renderer/components/ui/collapsible.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/collapsible.tsx
rename to apps/frontend/src/renderer/components/ui/collapsible.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/dialog.tsx b/apps/frontend/src/renderer/components/ui/dialog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/dialog.tsx
rename to apps/frontend/src/renderer/components/ui/dialog.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/dropdown-menu.tsx b/apps/frontend/src/renderer/components/ui/dropdown-menu.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/dropdown-menu.tsx
rename to apps/frontend/src/renderer/components/ui/dropdown-menu.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/full-screen-dialog.tsx b/apps/frontend/src/renderer/components/ui/full-screen-dialog.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/full-screen-dialog.tsx
rename to apps/frontend/src/renderer/components/ui/full-screen-dialog.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/index.ts b/apps/frontend/src/renderer/components/ui/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/index.ts
rename to apps/frontend/src/renderer/components/ui/index.ts
diff --git a/auto-claude-ui/src/renderer/components/ui/input.tsx b/apps/frontend/src/renderer/components/ui/input.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/input.tsx
rename to apps/frontend/src/renderer/components/ui/input.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/label.tsx b/apps/frontend/src/renderer/components/ui/label.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/label.tsx
rename to apps/frontend/src/renderer/components/ui/label.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/progress.tsx b/apps/frontend/src/renderer/components/ui/progress.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/progress.tsx
rename to apps/frontend/src/renderer/components/ui/progress.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/radio-group.tsx b/apps/frontend/src/renderer/components/ui/radio-group.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/radio-group.tsx
rename to apps/frontend/src/renderer/components/ui/radio-group.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/scroll-area.tsx b/apps/frontend/src/renderer/components/ui/scroll-area.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/scroll-area.tsx
rename to apps/frontend/src/renderer/components/ui/scroll-area.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/select.tsx b/apps/frontend/src/renderer/components/ui/select.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/select.tsx
rename to apps/frontend/src/renderer/components/ui/select.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/separator.tsx b/apps/frontend/src/renderer/components/ui/separator.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/separator.tsx
rename to apps/frontend/src/renderer/components/ui/separator.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/switch.tsx b/apps/frontend/src/renderer/components/ui/switch.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/switch.tsx
rename to apps/frontend/src/renderer/components/ui/switch.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/tabs.tsx b/apps/frontend/src/renderer/components/ui/tabs.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/tabs.tsx
rename to apps/frontend/src/renderer/components/ui/tabs.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/textarea.tsx b/apps/frontend/src/renderer/components/ui/textarea.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/textarea.tsx
rename to apps/frontend/src/renderer/components/ui/textarea.tsx
diff --git a/auto-claude-ui/src/renderer/components/ui/tooltip.tsx b/apps/frontend/src/renderer/components/ui/tooltip.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/components/ui/tooltip.tsx
rename to apps/frontend/src/renderer/components/ui/tooltip.tsx
diff --git a/auto-claude-ui/src/renderer/hooks/__tests__/useVirtualizedTree.test.ts b/apps/frontend/src/renderer/hooks/__tests__/useVirtualizedTree.test.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/hooks/__tests__/useVirtualizedTree.test.ts
rename to apps/frontend/src/renderer/hooks/__tests__/useVirtualizedTree.test.ts
diff --git a/auto-claude-ui/src/renderer/hooks/index.ts b/apps/frontend/src/renderer/hooks/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/hooks/index.ts
rename to apps/frontend/src/renderer/hooks/index.ts
diff --git a/auto-claude-ui/src/renderer/hooks/useClaudeAuth.ts b/apps/frontend/src/renderer/hooks/useClaudeAuth.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/hooks/useClaudeAuth.ts
rename to apps/frontend/src/renderer/hooks/useClaudeAuth.ts
diff --git a/auto-claude-ui/src/renderer/hooks/useEnvironmentConfig.ts b/apps/frontend/src/renderer/hooks/useEnvironmentConfig.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/hooks/useEnvironmentConfig.ts
rename to apps/frontend/src/renderer/hooks/useEnvironmentConfig.ts
diff --git a/auto-claude-ui/src/renderer/hooks/useGitHubConnection.ts b/apps/frontend/src/renderer/hooks/useGitHubConnection.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/hooks/useGitHubConnection.ts
rename to apps/frontend/src/renderer/hooks/useGitHubConnection.ts
diff --git a/auto-claude-ui/src/renderer/hooks/useInfrastructureStatus.ts b/apps/frontend/src/renderer/hooks/useInfrastructureStatus.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/hooks/useInfrastructureStatus.ts
rename to apps/frontend/src/renderer/hooks/useInfrastructureStatus.ts
diff --git a/auto-claude-ui/src/renderer/hooks/useIpc.ts b/apps/frontend/src/renderer/hooks/useIpc.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/hooks/useIpc.ts
rename to apps/frontend/src/renderer/hooks/useIpc.ts
diff --git a/auto-claude-ui/src/renderer/hooks/useLinearConnection.ts b/apps/frontend/src/renderer/hooks/useLinearConnection.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/hooks/useLinearConnection.ts
rename to apps/frontend/src/renderer/hooks/useLinearConnection.ts
diff --git a/auto-claude-ui/src/renderer/hooks/useProjectSettings.ts b/apps/frontend/src/renderer/hooks/useProjectSettings.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/hooks/useProjectSettings.ts
rename to apps/frontend/src/renderer/hooks/useProjectSettings.ts
diff --git a/auto-claude-ui/src/renderer/hooks/useVirtualizedTree.ts b/apps/frontend/src/renderer/hooks/useVirtualizedTree.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/hooks/useVirtualizedTree.ts
rename to apps/frontend/src/renderer/hooks/useVirtualizedTree.ts
diff --git a/auto-claude-ui/src/renderer/index.html b/apps/frontend/src/renderer/index.html
similarity index 100%
rename from auto-claude-ui/src/renderer/index.html
rename to apps/frontend/src/renderer/index.html
diff --git a/auto-claude-ui/src/renderer/lib/browser-mock.ts b/apps/frontend/src/renderer/lib/browser-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/browser-mock.ts
rename to apps/frontend/src/renderer/lib/browser-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/buffer-persistence.ts b/apps/frontend/src/renderer/lib/buffer-persistence.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/buffer-persistence.ts
rename to apps/frontend/src/renderer/lib/buffer-persistence.ts
diff --git a/auto-claude-ui/src/renderer/lib/flow-controller.ts b/apps/frontend/src/renderer/lib/flow-controller.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/flow-controller.ts
rename to apps/frontend/src/renderer/lib/flow-controller.ts
diff --git a/auto-claude-ui/src/renderer/lib/icons.ts b/apps/frontend/src/renderer/lib/icons.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/icons.ts
rename to apps/frontend/src/renderer/lib/icons.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/README.md b/apps/frontend/src/renderer/lib/mocks/README.md
similarity index 97%
rename from auto-claude-ui/src/renderer/lib/mocks/README.md
rename to apps/frontend/src/renderer/lib/mocks/README.md
index fbb0202b..7482215b 100644
--- a/auto-claude-ui/src/renderer/lib/mocks/README.md
+++ b/apps/frontend/src/renderer/lib/mocks/README.md
@@ -22,7 +22,7 @@ mocks/
├── integration-mock.ts # External integrations (Linear, GitHub)
├── changelog-mock.ts # Changelog and release operations
├── insights-mock.ts # AI insights and conversations
-├── infrastructure-mock.ts # Docker, FalkorDB, ideation, updates
+├── infrastructure-mock.ts # LadybugDB, memory, ideation, updates
└── settings-mock.ts # App settings and version info
```
diff --git a/auto-claude-ui/src/renderer/lib/mocks/changelog-mock.ts b/apps/frontend/src/renderer/lib/mocks/changelog-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/changelog-mock.ts
rename to apps/frontend/src/renderer/lib/mocks/changelog-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/claude-profile-mock.ts b/apps/frontend/src/renderer/lib/mocks/claude-profile-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/claude-profile-mock.ts
rename to apps/frontend/src/renderer/lib/mocks/claude-profile-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/context-mock.ts b/apps/frontend/src/renderer/lib/mocks/context-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/context-mock.ts
rename to apps/frontend/src/renderer/lib/mocks/context-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/index.ts b/apps/frontend/src/renderer/lib/mocks/index.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/index.ts
rename to apps/frontend/src/renderer/lib/mocks/index.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/infrastructure-mock.ts b/apps/frontend/src/renderer/lib/mocks/infrastructure-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/infrastructure-mock.ts
rename to apps/frontend/src/renderer/lib/mocks/infrastructure-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/insights-mock.ts b/apps/frontend/src/renderer/lib/mocks/insights-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/insights-mock.ts
rename to apps/frontend/src/renderer/lib/mocks/insights-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/integration-mock.ts b/apps/frontend/src/renderer/lib/mocks/integration-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/integration-mock.ts
rename to apps/frontend/src/renderer/lib/mocks/integration-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/mock-data.ts b/apps/frontend/src/renderer/lib/mocks/mock-data.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/mock-data.ts
rename to apps/frontend/src/renderer/lib/mocks/mock-data.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/project-mock.ts b/apps/frontend/src/renderer/lib/mocks/project-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/project-mock.ts
rename to apps/frontend/src/renderer/lib/mocks/project-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/roadmap-mock.ts b/apps/frontend/src/renderer/lib/mocks/roadmap-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/roadmap-mock.ts
rename to apps/frontend/src/renderer/lib/mocks/roadmap-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/settings-mock.ts b/apps/frontend/src/renderer/lib/mocks/settings-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/settings-mock.ts
rename to apps/frontend/src/renderer/lib/mocks/settings-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/task-mock.ts b/apps/frontend/src/renderer/lib/mocks/task-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/task-mock.ts
rename to apps/frontend/src/renderer/lib/mocks/task-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/terminal-mock.ts b/apps/frontend/src/renderer/lib/mocks/terminal-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/terminal-mock.ts
rename to apps/frontend/src/renderer/lib/mocks/terminal-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/mocks/workspace-mock.ts b/apps/frontend/src/renderer/lib/mocks/workspace-mock.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/mocks/workspace-mock.ts
rename to apps/frontend/src/renderer/lib/mocks/workspace-mock.ts
diff --git a/auto-claude-ui/src/renderer/lib/scroll-controller.ts b/apps/frontend/src/renderer/lib/scroll-controller.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/scroll-controller.ts
rename to apps/frontend/src/renderer/lib/scroll-controller.ts
diff --git a/auto-claude-ui/src/renderer/lib/terminal-buffer-manager.ts b/apps/frontend/src/renderer/lib/terminal-buffer-manager.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/terminal-buffer-manager.ts
rename to apps/frontend/src/renderer/lib/terminal-buffer-manager.ts
diff --git a/auto-claude-ui/src/renderer/lib/utils.ts b/apps/frontend/src/renderer/lib/utils.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/utils.ts
rename to apps/frontend/src/renderer/lib/utils.ts
diff --git a/auto-claude-ui/src/renderer/lib/webgl-context-manager.ts b/apps/frontend/src/renderer/lib/webgl-context-manager.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/webgl-context-manager.ts
rename to apps/frontend/src/renderer/lib/webgl-context-manager.ts
diff --git a/auto-claude-ui/src/renderer/lib/webgl-utils.ts b/apps/frontend/src/renderer/lib/webgl-utils.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/lib/webgl-utils.ts
rename to apps/frontend/src/renderer/lib/webgl-utils.ts
diff --git a/auto-claude-ui/src/renderer/main.tsx b/apps/frontend/src/renderer/main.tsx
similarity index 100%
rename from auto-claude-ui/src/renderer/main.tsx
rename to apps/frontend/src/renderer/main.tsx
diff --git a/auto-claude-ui/src/renderer/stores/changelog-store.ts b/apps/frontend/src/renderer/stores/changelog-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/changelog-store.ts
rename to apps/frontend/src/renderer/stores/changelog-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/claude-profile-store.ts b/apps/frontend/src/renderer/stores/claude-profile-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/claude-profile-store.ts
rename to apps/frontend/src/renderer/stores/claude-profile-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/context-store.ts b/apps/frontend/src/renderer/stores/context-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/context-store.ts
rename to apps/frontend/src/renderer/stores/context-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/file-explorer-store.ts b/apps/frontend/src/renderer/stores/file-explorer-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/file-explorer-store.ts
rename to apps/frontend/src/renderer/stores/file-explorer-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/github-store.ts b/apps/frontend/src/renderer/stores/github-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/github-store.ts
rename to apps/frontend/src/renderer/stores/github-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/ideation-store.ts b/apps/frontend/src/renderer/stores/ideation-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/ideation-store.ts
rename to apps/frontend/src/renderer/stores/ideation-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/insights-store.ts b/apps/frontend/src/renderer/stores/insights-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/insights-store.ts
rename to apps/frontend/src/renderer/stores/insights-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/project-store.ts b/apps/frontend/src/renderer/stores/project-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/project-store.ts
rename to apps/frontend/src/renderer/stores/project-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/rate-limit-store.ts b/apps/frontend/src/renderer/stores/rate-limit-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/rate-limit-store.ts
rename to apps/frontend/src/renderer/stores/rate-limit-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/release-store.ts b/apps/frontend/src/renderer/stores/release-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/release-store.ts
rename to apps/frontend/src/renderer/stores/release-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/roadmap-store.ts b/apps/frontend/src/renderer/stores/roadmap-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/roadmap-store.ts
rename to apps/frontend/src/renderer/stores/roadmap-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/settings-store.ts b/apps/frontend/src/renderer/stores/settings-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/settings-store.ts
rename to apps/frontend/src/renderer/stores/settings-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/task-store.ts b/apps/frontend/src/renderer/stores/task-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/task-store.ts
rename to apps/frontend/src/renderer/stores/task-store.ts
diff --git a/auto-claude-ui/src/renderer/stores/terminal-store.ts b/apps/frontend/src/renderer/stores/terminal-store.ts
similarity index 100%
rename from auto-claude-ui/src/renderer/stores/terminal-store.ts
rename to apps/frontend/src/renderer/stores/terminal-store.ts
diff --git a/auto-claude-ui/src/renderer/styles/globals.css b/apps/frontend/src/renderer/styles/globals.css
similarity index 100%
rename from auto-claude-ui/src/renderer/styles/globals.css
rename to apps/frontend/src/renderer/styles/globals.css
diff --git a/auto-claude-ui/src/shared/__tests__/progress.test.ts b/apps/frontend/src/shared/__tests__/progress.test.ts
similarity index 100%
rename from auto-claude-ui/src/shared/__tests__/progress.test.ts
rename to apps/frontend/src/shared/__tests__/progress.test.ts
diff --git a/auto-claude-ui/src/shared/constants.ts b/apps/frontend/src/shared/constants.ts
similarity index 100%
rename from auto-claude-ui/src/shared/constants.ts
rename to apps/frontend/src/shared/constants.ts
diff --git a/auto-claude-ui/src/shared/constants/changelog.ts b/apps/frontend/src/shared/constants/changelog.ts
similarity index 100%
rename from auto-claude-ui/src/shared/constants/changelog.ts
rename to apps/frontend/src/shared/constants/changelog.ts
diff --git a/auto-claude-ui/src/shared/constants/config.ts b/apps/frontend/src/shared/constants/config.ts
similarity index 100%
rename from auto-claude-ui/src/shared/constants/config.ts
rename to apps/frontend/src/shared/constants/config.ts
diff --git a/auto-claude-ui/src/shared/constants/github.ts b/apps/frontend/src/shared/constants/github.ts
similarity index 100%
rename from auto-claude-ui/src/shared/constants/github.ts
rename to apps/frontend/src/shared/constants/github.ts
diff --git a/auto-claude-ui/src/shared/constants/ideation.ts b/apps/frontend/src/shared/constants/ideation.ts
similarity index 100%
rename from auto-claude-ui/src/shared/constants/ideation.ts
rename to apps/frontend/src/shared/constants/ideation.ts
diff --git a/auto-claude-ui/src/shared/constants/index.ts b/apps/frontend/src/shared/constants/index.ts
similarity index 100%
rename from auto-claude-ui/src/shared/constants/index.ts
rename to apps/frontend/src/shared/constants/index.ts
diff --git a/auto-claude-ui/src/shared/constants/ipc.ts b/apps/frontend/src/shared/constants/ipc.ts
similarity index 100%
rename from auto-claude-ui/src/shared/constants/ipc.ts
rename to apps/frontend/src/shared/constants/ipc.ts
diff --git a/auto-claude-ui/src/shared/constants/models.ts b/apps/frontend/src/shared/constants/models.ts
similarity index 100%
rename from auto-claude-ui/src/shared/constants/models.ts
rename to apps/frontend/src/shared/constants/models.ts
diff --git a/auto-claude-ui/src/shared/constants/roadmap.ts b/apps/frontend/src/shared/constants/roadmap.ts
similarity index 100%
rename from auto-claude-ui/src/shared/constants/roadmap.ts
rename to apps/frontend/src/shared/constants/roadmap.ts
diff --git a/auto-claude-ui/src/shared/constants/task.ts b/apps/frontend/src/shared/constants/task.ts
similarity index 100%
rename from auto-claude-ui/src/shared/constants/task.ts
rename to apps/frontend/src/shared/constants/task.ts
diff --git a/auto-claude-ui/src/shared/constants/themes.ts b/apps/frontend/src/shared/constants/themes.ts
similarity index 100%
rename from auto-claude-ui/src/shared/constants/themes.ts
rename to apps/frontend/src/shared/constants/themes.ts
diff --git a/auto-claude-ui/src/shared/progress.ts b/apps/frontend/src/shared/progress.ts
similarity index 100%
rename from auto-claude-ui/src/shared/progress.ts
rename to apps/frontend/src/shared/progress.ts
diff --git a/auto-claude-ui/src/shared/types.ts b/apps/frontend/src/shared/types.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types.ts
rename to apps/frontend/src/shared/types.ts
diff --git a/auto-claude-ui/src/shared/types/agent.ts b/apps/frontend/src/shared/types/agent.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/agent.ts
rename to apps/frontend/src/shared/types/agent.ts
diff --git a/auto-claude-ui/src/shared/types/app-update.ts b/apps/frontend/src/shared/types/app-update.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/app-update.ts
rename to apps/frontend/src/shared/types/app-update.ts
diff --git a/auto-claude-ui/src/shared/types/changelog.ts b/apps/frontend/src/shared/types/changelog.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/changelog.ts
rename to apps/frontend/src/shared/types/changelog.ts
diff --git a/auto-claude-ui/src/shared/types/common.ts b/apps/frontend/src/shared/types/common.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/common.ts
rename to apps/frontend/src/shared/types/common.ts
diff --git a/auto-claude-ui/src/shared/types/index.ts b/apps/frontend/src/shared/types/index.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/index.ts
rename to apps/frontend/src/shared/types/index.ts
diff --git a/auto-claude-ui/src/shared/types/insights.ts b/apps/frontend/src/shared/types/insights.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/insights.ts
rename to apps/frontend/src/shared/types/insights.ts
diff --git a/auto-claude-ui/src/shared/types/integrations.ts b/apps/frontend/src/shared/types/integrations.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/integrations.ts
rename to apps/frontend/src/shared/types/integrations.ts
diff --git a/auto-claude-ui/src/shared/types/ipc.ts b/apps/frontend/src/shared/types/ipc.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/ipc.ts
rename to apps/frontend/src/shared/types/ipc.ts
diff --git a/auto-claude-ui/src/shared/types/project.ts b/apps/frontend/src/shared/types/project.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/project.ts
rename to apps/frontend/src/shared/types/project.ts
diff --git a/auto-claude-ui/src/shared/types/roadmap.ts b/apps/frontend/src/shared/types/roadmap.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/roadmap.ts
rename to apps/frontend/src/shared/types/roadmap.ts
diff --git a/auto-claude-ui/src/shared/types/settings.ts b/apps/frontend/src/shared/types/settings.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/settings.ts
rename to apps/frontend/src/shared/types/settings.ts
diff --git a/auto-claude-ui/src/shared/types/task.ts b/apps/frontend/src/shared/types/task.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/task.ts
rename to apps/frontend/src/shared/types/task.ts
diff --git a/auto-claude-ui/src/shared/types/terminal-session.ts b/apps/frontend/src/shared/types/terminal-session.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/terminal-session.ts
rename to apps/frontend/src/shared/types/terminal-session.ts
diff --git a/auto-claude-ui/src/shared/types/terminal.ts b/apps/frontend/src/shared/types/terminal.ts
similarity index 100%
rename from auto-claude-ui/src/shared/types/terminal.ts
rename to apps/frontend/src/shared/types/terminal.ts
diff --git a/auto-claude-ui/src/shared/utils/debug-logger.ts b/apps/frontend/src/shared/utils/debug-logger.ts
similarity index 100%
rename from auto-claude-ui/src/shared/utils/debug-logger.ts
rename to apps/frontend/src/shared/utils/debug-logger.ts
diff --git a/auto-claude-ui/src/shared/utils/shell-escape.ts b/apps/frontend/src/shared/utils/shell-escape.ts
similarity index 100%
rename from auto-claude-ui/src/shared/utils/shell-escape.ts
rename to apps/frontend/src/shared/utils/shell-escape.ts
diff --git a/auto-claude-ui/tsconfig.json b/apps/frontend/tsconfig.json
similarity index 68%
rename from auto-claude-ui/tsconfig.json
rename to apps/frontend/tsconfig.json
index 1cfff5f5..30866c15 100644
--- a/auto-claude-ui/tsconfig.json
+++ b/apps/frontend/tsconfig.json
@@ -15,7 +15,11 @@
"baseUrl": ".",
"paths": {
"@/*": ["src/renderer/*"],
- "@shared/*": ["src/shared/*"]
+ "@shared/*": ["src/shared/*"],
+ "@features/*": ["src/renderer/features/*"],
+ "@components/*": ["src/renderer/shared/components/*"],
+ "@hooks/*": ["src/renderer/shared/hooks/*"],
+ "@lib/*": ["src/renderer/shared/lib/*"]
}
},
"include": ["src/**/*"],
diff --git a/auto-claude-ui/vitest.config.ts b/apps/frontend/vitest.config.ts
similarity index 100%
rename from auto-claude-ui/vitest.config.ts
rename to apps/frontend/vitest.config.ts
diff --git a/auto-claude-ui/.husky/pre-commit b/auto-claude-ui/.husky/pre-commit
deleted file mode 100644
index 98475b50..00000000
--- a/auto-claude-ui/.husky/pre-commit
+++ /dev/null
@@ -1 +0,0 @@
-pnpm test
diff --git a/auto-claude-ui/.npmrc b/auto-claude-ui/.npmrc
deleted file mode 100644
index 9bfb782b..00000000
--- a/auto-claude-ui/.npmrc
+++ /dev/null
@@ -1 +0,0 @@
-side-effects-cache=true
diff --git a/auto-claude-ui/README.md b/auto-claude-ui/README.md
deleted file mode 100644
index c4230d1c..00000000
--- a/auto-claude-ui/README.md
+++ /dev/null
@@ -1,131 +0,0 @@
-# Auto Claude UI
-
-A desktop application for managing AI-driven development tasks using the Auto Claude autonomous coding framework.
-
-## Quick Start
-
-```bash
-# 1. Clone the repo (if you haven't already)
-git clone https://github.com/AndyMik90/Auto-Claude.git
-cd Auto-Claude/auto-claude-ui
-
-# 2. Install dependencies
-npm install
-
-# 3. Build the desktop app
-npm run package:win # Windows
-npm run package:mac # macOS
-npm run package:linux # Linux
-
-# 4. Run the app
-# Windows: .\dist\win-unpacked\Auto Claude.exe
-# macOS: open dist/mac-arm64/Auto\ Claude.app
-# Linux: ./dist/linux-unpacked/auto-claude
-```
-
-## Prerequisites
-
-- Node.js 18+
-- npm or pnpm
-- Python 3.10+ (for auto-claude backend)
-- **Windows only**: Visual Studio Build Tools 2022 with "Desktop development with C++" workload
-- **Windows only**: Developer Mode enabled (Settings → System → For developers)
-
-## How to Run
-
-### Building for Production (Recommended)
-
-Build the Electron desktop app for your platform:
-
-```bash
-# Build for Windows
-npm run package:win
-
-# Build for macOS
-npm run package:mac
-
-# Build for Linux
-npm run package:linux
-```
-
-### Running the Production Build
-
-After building, run the application from the `dist` folder:
-
-```bash
-# Windows - run the executable
-.\dist\win-unpacked\Auto Claude.exe
-
-# Windows - or use the installer
-.\dist\Auto Claude Setup X.X.X.exe
-
-# macOS
-open dist/mac-arm64/Auto\ Claude.app
-
-# Linux
-./dist/linux-unpacked/auto-claude
-```
-
-### Development Mode
-
-For development with hot reload (optional):
-
-```bash
-npm run dev
-```
-
-> **Note**: Some features like auto-updates only work in packaged builds.
-
-## Distribution Files
-
-After packaging, the `dist` folder contains:
-
-| Platform | Files |
-|----------|-------|
-| macOS | `Auto Claude.app`, `.dmg`, `.zip` |
-| Windows | `Auto Claude Setup X.X.X.exe` (installer), `.zip`, `win-unpacked/` |
-| Linux | `.AppImage`, `.deb`, `linux-unpacked/` |
-
-## Testing
-
-```bash
-# Run tests
-npm run test
-```
-
-## Linting
-
-```bash
-# Run ESLint
-npm run lint
-
-# Run type checking
-npm run typecheck
-```
-
-## Features
-
-- **Project Management**: Add, configure, and switch between multiple projects
-- **Kanban Board**: Visual task board with columns for Backlog, In Progress, AI Review, Human Review, and Done
-- **Task Creation Wizard**: Form-based interface for creating new tasks
-- **Real-Time Progress**: Live updates during agent execution
-- **Human Review Workflow**: Review QA results and provide feedback
-- **Theme Support**: Light and dark mode
-- **Auto Updates**: Automatic update notifications
-
-## Tech Stack
-
-- **Framework**: Electron + React 18 (TypeScript)
-- **Build Tool**: electron-vite + electron-builder
-- **UI Components**: Radix UI (shadcn/ui pattern)
-- **Styling**: TailwindCSS
-- **State Management**: Zustand
-
-## Environment Variables
-
-- `CLAUDE_CODE_OAUTH_TOKEN`: OAuth token for Claude Code SDK (from auto-claude/.env)
-- `FALKORDB_URL`: FalkorDB connection URL (optional)
-
-## License
-
-AGPL-3.0
diff --git a/auto-claude-ui/pnpm-lock.yaml b/auto-claude-ui/pnpm-lock.yaml
deleted file mode 100644
index 808e9cb7..00000000
--- a/auto-claude-ui/pnpm-lock.yaml
+++ /dev/null
@@ -1,9588 +0,0 @@
-lockfileVersion: '9.0'
-
-settings:
- autoInstallPeers: true
- excludeLinksFromLockfile: false
-
-overrides:
- electron-builder-squirrel-windows: ^26.0.12
- dmg-builder: ^26.0.12
- node-pty: npm:@lydell/node-pty@^1.1.0
-
-importers:
-
- .:
- dependencies:
- '@dnd-kit/core':
- specifier: ^6.3.1
- version: 6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@dnd-kit/sortable':
- specifier: ^10.0.0
- version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)
- '@dnd-kit/utilities':
- specifier: ^3.2.2
- version: 3.2.2(react@19.2.3)
- '@lydell/node-pty':
- specifier: ^1.1.0
- version: 1.1.0
- '@radix-ui/react-alert-dialog':
- specifier: ^1.1.15
- version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-checkbox':
- specifier: ^1.1.4
- version: 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-collapsible':
- specifier: ^1.1.3
- version: 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-dialog':
- specifier: ^1.1.15
- version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-dropdown-menu':
- specifier: ^2.1.16
- version: 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-progress':
- specifier: ^1.1.8
- version: 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-radio-group':
- specifier: ^1.3.8
- version: 1.3.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-scroll-area':
- specifier: ^1.2.10
- version: 1.2.10(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-select':
- specifier: ^2.2.6
- version: 2.2.6(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-separator':
- specifier: ^1.1.8
- version: 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-slot':
- specifier: ^1.2.4
- version: 1.2.4(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-switch':
- specifier: ^1.2.6
- version: 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-tabs':
- specifier: ^1.1.13
- version: 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-toast':
- specifier: ^1.2.15
- version: 1.2.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-tooltip':
- specifier: ^1.2.8
- version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@tailwindcss/typography':
- specifier: ^0.5.19
- version: 0.5.19(tailwindcss@4.1.18)
- '@tanstack/react-virtual':
- specifier: ^3.13.13
- version: 3.13.13(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@xterm/addon-fit':
- specifier: ^0.10.0
- version: 0.10.0(@xterm/xterm@5.5.0)
- '@xterm/addon-serialize':
- specifier: ^0.13.0
- version: 0.13.0(@xterm/xterm@5.5.0)
- '@xterm/addon-web-links':
- specifier: ^0.11.0
- version: 0.11.0(@xterm/xterm@5.5.0)
- '@xterm/addon-webgl':
- specifier: ^0.18.0
- version: 0.18.0(@xterm/xterm@5.5.0)
- '@xterm/xterm':
- specifier: ^5.5.0
- version: 5.5.0
- chokidar:
- specifier: ^5.0.0
- version: 5.0.0
- class-variance-authority:
- specifier: ^0.7.1
- version: 0.7.1
- clsx:
- specifier: ^2.1.1
- version: 2.1.1
- electron-updater:
- specifier: ^6.6.2
- version: 6.6.2
- lucide-react:
- specifier: ^0.560.0
- version: 0.560.0(react@19.2.3)
- motion:
- specifier: ^12.23.26
- version: 12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- react:
- specifier: ^19.2.3
- version: 19.2.3
- react-dom:
- specifier: ^19.2.3
- version: 19.2.3(react@19.2.3)
- react-markdown:
- specifier: ^10.1.0
- version: 10.1.0(@types/react@19.2.7)(react@19.2.3)
- react-resizable-panels:
- specifier: ^3.0.6
- version: 3.0.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- remark-gfm:
- specifier: ^4.0.1
- version: 4.0.1
- tailwind-merge:
- specifier: ^3.4.0
- version: 3.4.0
- uuid:
- specifier: ^13.0.0
- version: 13.0.0
- zustand:
- specifier: ^5.0.9
- version: 5.0.9(@types/react@19.2.7)(react@19.2.3)
- devDependencies:
- '@electron-toolkit/preload':
- specifier: ^3.0.2
- version: 3.0.2(electron@39.2.7)
- '@electron-toolkit/utils':
- specifier: ^4.0.0
- version: 4.0.0(electron@39.2.7)
- '@electron/rebuild':
- specifier: ^3.7.1
- version: 3.7.2
- '@eslint/js':
- specifier: ^9.39.1
- version: 9.39.2
- '@playwright/test':
- specifier: ^1.52.0
- version: 1.57.0
- '@tailwindcss/postcss':
- specifier: ^4.1.17
- version: 4.1.18
- '@testing-library/react':
- specifier: ^16.1.0
- version: 16.3.1(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@types/node':
- specifier: ^25.0.0
- version: 25.0.3
- '@types/react':
- specifier: ^19.2.7
- version: 19.2.7
- '@types/react-dom':
- specifier: ^19.2.3
- version: 19.2.3(@types/react@19.2.7)
- '@types/uuid':
- specifier: ^10.0.0
- version: 10.0.0
- '@vitejs/plugin-react':
- specifier: ^5.1.2
- version: 5.1.2(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))
- autoprefixer:
- specifier: ^10.4.22
- version: 10.4.23(postcss@8.5.6)
- electron:
- specifier: ^39.2.6
- version: 39.2.7
- electron-builder:
- specifier: ^26.0.12
- version: 26.0.12(electron-builder-squirrel-windows@26.0.12)
- electron-vite:
- specifier: ^5.0.0
- version: 5.0.0(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))
- eslint:
- specifier: ^9.39.1
- version: 9.39.2(jiti@2.6.1)
- eslint-plugin-react:
- specifier: ^7.37.5
- version: 7.37.5(eslint@9.39.2(jiti@2.6.1))
- eslint-plugin-react-hooks:
- specifier: ^7.0.1
- version: 7.0.1(eslint@9.39.2(jiti@2.6.1))
- globals:
- specifier: ^16.5.0
- version: 16.5.0
- husky:
- specifier: ^9.1.7
- version: 9.1.7
- jsdom:
- specifier: ^26.0.0
- version: 26.1.0
- lint-staged:
- specifier: ^16.2.7
- version: 16.2.7
- postcss:
- specifier: ^8.5.6
- version: 8.5.6
- tailwindcss:
- specifier: ^4.1.17
- version: 4.1.18
- typescript:
- specifier: ^5.9.3
- version: 5.9.3
- typescript-eslint:
- specifier: ^8.49.0
- version: 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- vite:
- specifier: ^7.2.7
- version: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)
- vitest:
- specifier: ^4.0.15
- version: 4.0.16(@types/node@25.0.3)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(yaml@2.8.2)
-
-packages:
-
- 7zip-bin@5.2.0:
- resolution: {integrity: sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==}
-
- '@alloc/quick-lru@5.2.0':
- resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
- engines: {node: '>=10'}
-
- '@asamuzakjp/css-color@3.2.0':
- resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==}
-
- '@babel/code-frame@7.27.1':
- resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
- engines: {node: '>=6.9.0'}
-
- '@babel/compat-data@7.28.5':
- resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==}
- engines: {node: '>=6.9.0'}
-
- '@babel/core@7.28.5':
- resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==}
- engines: {node: '>=6.9.0'}
-
- '@babel/generator@7.28.5':
- resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-compilation-targets@7.27.2':
- resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-globals@7.28.0':
- resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-module-imports@7.27.1':
- resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-module-transforms@7.28.3':
- resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0
-
- '@babel/helper-plugin-utils@7.27.1':
- resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-string-parser@7.27.1':
- resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-validator-identifier@7.28.5':
- resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-validator-option@7.27.1':
- resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helpers@7.28.4':
- resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==}
- engines: {node: '>=6.9.0'}
-
- '@babel/parser@7.28.5':
- resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==}
- engines: {node: '>=6.0.0'}
- hasBin: true
-
- '@babel/plugin-transform-arrow-functions@7.27.1':
- resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@babel/plugin-transform-react-jsx-self@7.27.1':
- resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@babel/plugin-transform-react-jsx-source@7.27.1':
- resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@babel/runtime@7.28.4':
- resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
- engines: {node: '>=6.9.0'}
-
- '@babel/template@7.27.2':
- resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
- engines: {node: '>=6.9.0'}
-
- '@babel/traverse@7.28.5':
- resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==}
- engines: {node: '>=6.9.0'}
-
- '@babel/types@7.28.5':
- resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
- engines: {node: '>=6.9.0'}
-
- '@csstools/color-helpers@5.1.0':
- resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==}
- engines: {node: '>=18'}
-
- '@csstools/css-calc@2.1.4':
- resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==}
- engines: {node: '>=18'}
- peerDependencies:
- '@csstools/css-parser-algorithms': ^3.0.5
- '@csstools/css-tokenizer': ^3.0.4
-
- '@csstools/css-color-parser@3.1.0':
- resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==}
- engines: {node: '>=18'}
- peerDependencies:
- '@csstools/css-parser-algorithms': ^3.0.5
- '@csstools/css-tokenizer': ^3.0.4
-
- '@csstools/css-parser-algorithms@3.0.5':
- resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==}
- engines: {node: '>=18'}
- peerDependencies:
- '@csstools/css-tokenizer': ^3.0.4
-
- '@csstools/css-tokenizer@3.0.4':
- resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==}
- engines: {node: '>=18'}
-
- '@develar/schema-utils@2.6.5':
- resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==}
- engines: {node: '>= 8.9.0'}
-
- '@dnd-kit/accessibility@3.1.1':
- resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==}
- peerDependencies:
- react: '>=16.8.0'
-
- '@dnd-kit/core@6.3.1':
- resolution: {integrity: sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==}
- peerDependencies:
- react: '>=16.8.0'
- react-dom: '>=16.8.0'
-
- '@dnd-kit/sortable@10.0.0':
- resolution: {integrity: sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==}
- peerDependencies:
- '@dnd-kit/core': ^6.3.0
- react: '>=16.8.0'
-
- '@dnd-kit/utilities@3.2.2':
- resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==}
- peerDependencies:
- react: '>=16.8.0'
-
- '@electron-toolkit/preload@3.0.2':
- resolution: {integrity: sha512-TWWPToXd8qPRfSXwzf5KVhpXMfONaUuRAZJHsKthKgZR/+LqX1dZVSSClQ8OTAEduvLGdecljCsoT2jSshfoUg==}
- peerDependencies:
- electron: '>=13.0.0'
-
- '@electron-toolkit/utils@4.0.0':
- resolution: {integrity: sha512-qXSntwEzluSzKl4z5yFNBknmPGjPa3zFhE4mp9+h0cgokY5ornAeP+CJQDBhKsL1S58aOQfcwkD3NwLZCl+64g==}
- peerDependencies:
- electron: '>=13.0.0'
-
- '@electron/asar@3.2.18':
- resolution: {integrity: sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==}
- engines: {node: '>=10.12.0'}
- hasBin: true
-
- '@electron/asar@3.4.1':
- resolution: {integrity: sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==}
- engines: {node: '>=10.12.0'}
- hasBin: true
-
- '@electron/fuses@1.8.0':
- resolution: {integrity: sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==}
- hasBin: true
-
- '@electron/get@2.0.3':
- resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==}
- engines: {node: '>=12'}
-
- '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2':
- resolution: {tarball: https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2}
- version: 10.2.0-electron.1
- engines: {node: '>=12.13.0'}
- hasBin: true
-
- '@electron/notarize@2.5.0':
- resolution: {integrity: sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==}
- engines: {node: '>= 10.0.0'}
-
- '@electron/osx-sign@1.3.1':
- resolution: {integrity: sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==}
- engines: {node: '>=12.0.0'}
- hasBin: true
-
- '@electron/rebuild@3.7.0':
- resolution: {integrity: sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==}
- engines: {node: '>=12.13.0'}
- hasBin: true
-
- '@electron/rebuild@3.7.2':
- resolution: {integrity: sha512-19/KbIR/DAxbsCkiaGMXIdPnMCJLkcf8AvGnduJtWBs/CBwiAjY1apCqOLVxrXg+rtXFCngbXhBanWjxLUt1Mg==}
- engines: {node: '>=12.13.0'}
- hasBin: true
-
- '@electron/universal@2.0.1':
- resolution: {integrity: sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==}
- engines: {node: '>=16.4'}
-
- '@electron/windows-sign@1.2.2':
- resolution: {integrity: sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==}
- engines: {node: '>=14.14'}
- hasBin: true
-
- '@esbuild/aix-ppc64@0.25.12':
- resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==}
- engines: {node: '>=18'}
- cpu: [ppc64]
- os: [aix]
-
- '@esbuild/aix-ppc64@0.27.2':
- resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
- engines: {node: '>=18'}
- cpu: [ppc64]
- os: [aix]
-
- '@esbuild/android-arm64@0.25.12':
- resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [android]
-
- '@esbuild/android-arm64@0.27.2':
- resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [android]
-
- '@esbuild/android-arm@0.25.12':
- resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
- engines: {node: '>=18'}
- cpu: [arm]
- os: [android]
-
- '@esbuild/android-arm@0.27.2':
- resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==}
- engines: {node: '>=18'}
- cpu: [arm]
- os: [android]
-
- '@esbuild/android-x64@0.25.12':
- resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [android]
-
- '@esbuild/android-x64@0.27.2':
- resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [android]
-
- '@esbuild/darwin-arm64@0.25.12':
- resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [darwin]
-
- '@esbuild/darwin-arm64@0.27.2':
- resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [darwin]
-
- '@esbuild/darwin-x64@0.25.12':
- resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [darwin]
-
- '@esbuild/darwin-x64@0.27.2':
- resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [darwin]
-
- '@esbuild/freebsd-arm64@0.25.12':
- resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [freebsd]
-
- '@esbuild/freebsd-arm64@0.27.2':
- resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [freebsd]
-
- '@esbuild/freebsd-x64@0.25.12':
- resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [freebsd]
-
- '@esbuild/freebsd-x64@0.27.2':
- resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [freebsd]
-
- '@esbuild/linux-arm64@0.25.12':
- resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [linux]
-
- '@esbuild/linux-arm64@0.27.2':
- resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [linux]
-
- '@esbuild/linux-arm@0.25.12':
- resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==}
- engines: {node: '>=18'}
- cpu: [arm]
- os: [linux]
-
- '@esbuild/linux-arm@0.27.2':
- resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==}
- engines: {node: '>=18'}
- cpu: [arm]
- os: [linux]
-
- '@esbuild/linux-ia32@0.25.12':
- resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
- engines: {node: '>=18'}
- cpu: [ia32]
- os: [linux]
-
- '@esbuild/linux-ia32@0.27.2':
- resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==}
- engines: {node: '>=18'}
- cpu: [ia32]
- os: [linux]
-
- '@esbuild/linux-loong64@0.25.12':
- resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==}
- engines: {node: '>=18'}
- cpu: [loong64]
- os: [linux]
-
- '@esbuild/linux-loong64@0.27.2':
- resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==}
- engines: {node: '>=18'}
- cpu: [loong64]
- os: [linux]
-
- '@esbuild/linux-mips64el@0.25.12':
- resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
- engines: {node: '>=18'}
- cpu: [mips64el]
- os: [linux]
-
- '@esbuild/linux-mips64el@0.27.2':
- resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==}
- engines: {node: '>=18'}
- cpu: [mips64el]
- os: [linux]
-
- '@esbuild/linux-ppc64@0.25.12':
- resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==}
- engines: {node: '>=18'}
- cpu: [ppc64]
- os: [linux]
-
- '@esbuild/linux-ppc64@0.27.2':
- resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==}
- engines: {node: '>=18'}
- cpu: [ppc64]
- os: [linux]
-
- '@esbuild/linux-riscv64@0.25.12':
- resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
- engines: {node: '>=18'}
- cpu: [riscv64]
- os: [linux]
-
- '@esbuild/linux-riscv64@0.27.2':
- resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==}
- engines: {node: '>=18'}
- cpu: [riscv64]
- os: [linux]
-
- '@esbuild/linux-s390x@0.25.12':
- resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==}
- engines: {node: '>=18'}
- cpu: [s390x]
- os: [linux]
-
- '@esbuild/linux-s390x@0.27.2':
- resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==}
- engines: {node: '>=18'}
- cpu: [s390x]
- os: [linux]
-
- '@esbuild/linux-x64@0.25.12':
- resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [linux]
-
- '@esbuild/linux-x64@0.27.2':
- resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [linux]
-
- '@esbuild/netbsd-arm64@0.25.12':
- resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [netbsd]
-
- '@esbuild/netbsd-arm64@0.27.2':
- resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [netbsd]
-
- '@esbuild/netbsd-x64@0.25.12':
- resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [netbsd]
-
- '@esbuild/netbsd-x64@0.27.2':
- resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [netbsd]
-
- '@esbuild/openbsd-arm64@0.25.12':
- resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [openbsd]
-
- '@esbuild/openbsd-arm64@0.27.2':
- resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [openbsd]
-
- '@esbuild/openbsd-x64@0.25.12':
- resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [openbsd]
-
- '@esbuild/openbsd-x64@0.27.2':
- resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [openbsd]
-
- '@esbuild/openharmony-arm64@0.25.12':
- resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [openharmony]
-
- '@esbuild/openharmony-arm64@0.27.2':
- resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [openharmony]
-
- '@esbuild/sunos-x64@0.25.12':
- resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [sunos]
-
- '@esbuild/sunos-x64@0.27.2':
- resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [sunos]
-
- '@esbuild/win32-arm64@0.25.12':
- resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [win32]
-
- '@esbuild/win32-arm64@0.27.2':
- resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==}
- engines: {node: '>=18'}
- cpu: [arm64]
- os: [win32]
-
- '@esbuild/win32-ia32@0.25.12':
- resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
- engines: {node: '>=18'}
- cpu: [ia32]
- os: [win32]
-
- '@esbuild/win32-ia32@0.27.2':
- resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==}
- engines: {node: '>=18'}
- cpu: [ia32]
- os: [win32]
-
- '@esbuild/win32-x64@0.25.12':
- resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [win32]
-
- '@esbuild/win32-x64@0.27.2':
- resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==}
- engines: {node: '>=18'}
- cpu: [x64]
- os: [win32]
-
- '@eslint-community/eslint-utils@4.9.0':
- resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- peerDependencies:
- eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
-
- '@eslint-community/regexpp@4.12.2':
- resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
- engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
-
- '@eslint/config-array@0.21.1':
- resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/config-helpers@0.4.2':
- resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/core@0.17.0':
- resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/eslintrc@3.3.3':
- resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/js@9.39.2':
- resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/object-schema@2.1.7':
- resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/plugin-kit@0.4.1':
- resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@floating-ui/core@1.7.3':
- resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==}
-
- '@floating-ui/dom@1.7.4':
- resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==}
-
- '@floating-ui/react-dom@2.1.6':
- resolution: {integrity: sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==}
- peerDependencies:
- react: '>=16.8.0'
- react-dom: '>=16.8.0'
-
- '@floating-ui/utils@0.2.10':
- resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
-
- '@gar/promisify@1.1.3':
- resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
-
- '@humanfs/core@0.19.1':
- resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
- engines: {node: '>=18.18.0'}
-
- '@humanfs/node@0.16.7':
- resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==}
- engines: {node: '>=18.18.0'}
-
- '@humanwhocodes/module-importer@1.0.1':
- resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
- engines: {node: '>=12.22'}
-
- '@humanwhocodes/retry@0.4.3':
- resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
- engines: {node: '>=18.18'}
-
- '@isaacs/balanced-match@4.0.1':
- resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
- engines: {node: 20 || >=22}
-
- '@isaacs/brace-expansion@5.0.0':
- resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==}
- engines: {node: 20 || >=22}
-
- '@isaacs/cliui@8.0.2':
- resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
- engines: {node: '>=12'}
-
- '@jridgewell/gen-mapping@0.3.13':
- resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
-
- '@jridgewell/remapping@2.3.5':
- resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
-
- '@jridgewell/resolve-uri@3.1.2':
- resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
- engines: {node: '>=6.0.0'}
-
- '@jridgewell/sourcemap-codec@1.5.5':
- resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
-
- '@jridgewell/trace-mapping@0.3.31':
- resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
-
- '@lydell/node-pty-darwin-arm64@1.1.0':
- resolution: {integrity: sha512-7kFD+owAA61qmhJCtoMbqj3Uvff3YHDiU+4on5F2vQdcMI3MuwGi7dM6MkFG/yuzpw8LF2xULpL71tOPUfxs0w==}
- cpu: [arm64]
- os: [darwin]
-
- '@lydell/node-pty-darwin-x64@1.1.0':
- resolution: {integrity: sha512-XZdvqj5FjAMjH8bdp0YfaZjur5DrCIDD1VYiE9EkkYVMDQqRUPHYV3U8BVEQVT9hYfjmpr7dNaELF2KyISWSNA==}
- cpu: [x64]
- os: [darwin]
-
- '@lydell/node-pty-linux-arm64@1.1.0':
- resolution: {integrity: sha512-yyDBmalCfHpLiQMT2zyLcqL2Fay4Xy7rIs8GH4dqKLnEviMvPGOK7LADVkKAsbsyXBSISL3Lt1m1MtxhPH6ckg==}
- cpu: [arm64]
- os: [linux]
-
- '@lydell/node-pty-linux-x64@1.1.0':
- resolution: {integrity: sha512-NcNqRTD14QT+vXcEuqSSvmWY+0+WUBn2uRE8EN0zKtDpIEr9d+YiFj16Uqds6QfcLCHfZmC+Ls7YzwTaqDnanA==}
- cpu: [x64]
- os: [linux]
-
- '@lydell/node-pty-win32-arm64@1.1.0':
- resolution: {integrity: sha512-JOMbCou+0fA7d/m97faIIfIU0jOv8sn2OR7tI45u3AmldKoKoLP8zHY6SAvDDnI3fccO1R2HeR1doVjpS7HM0w==}
- cpu: [arm64]
- os: [win32]
-
- '@lydell/node-pty-win32-x64@1.1.0':
- resolution: {integrity: sha512-3N56BZ+WDFnUMYRtsrr7Ky2mhWGl9xXcyqR6cexfuCqcz9RNWL+KoXRv/nZylY5dYaXkft4JaR1uVu+roiZDAw==}
- cpu: [x64]
- os: [win32]
-
- '@lydell/node-pty@1.1.0':
- resolution: {integrity: sha512-VDD8LtlMTOrPKWMXUAcB9+LTktzuunqrMwkYR1DMRBkS6LQrCt+0/Ws1o2rMml/n3guePpS7cxhHF7Nm5K4iMw==}
-
- '@malept/cross-spawn-promise@2.0.0':
- resolution: {integrity: sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==}
- engines: {node: '>= 12.13.0'}
-
- '@malept/flatpak-bundler@0.4.0':
- resolution: {integrity: sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==}
- engines: {node: '>= 10.0.0'}
-
- '@npmcli/fs@2.1.2':
- resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==}
- engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
-
- '@npmcli/move-file@2.0.1':
- resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==}
- engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
- deprecated: This functionality has been moved to @npmcli/fs
-
- '@pkgjs/parseargs@0.11.0':
- resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
- engines: {node: '>=14'}
-
- '@playwright/test@1.57.0':
- resolution: {integrity: sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==}
- engines: {node: '>=18'}
- hasBin: true
-
- '@radix-ui/number@1.1.1':
- resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==}
-
- '@radix-ui/primitive@1.1.3':
- resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==}
-
- '@radix-ui/react-alert-dialog@1.1.15':
- resolution: {integrity: sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-arrow@1.1.7':
- resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-checkbox@1.3.3':
- resolution: {integrity: sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-collapsible@1.1.12':
- resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-collection@1.1.7':
- resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-compose-refs@1.1.2':
- resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-context@1.1.2':
- resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-context@1.1.3':
- resolution: {integrity: sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-dialog@1.1.15':
- resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-direction@1.1.1':
- resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-dismissable-layer@1.1.11':
- resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-dropdown-menu@2.1.16':
- resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-focus-guards@1.1.3':
- resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-focus-scope@1.1.7':
- resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-id@1.1.1':
- resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-menu@2.1.16':
- resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-popper@1.2.8':
- resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-portal@1.1.9':
- resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-presence@1.1.5':
- resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-primitive@2.1.3':
- resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-primitive@2.1.4':
- resolution: {integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-progress@1.1.8':
- resolution: {integrity: sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-radio-group@1.3.8':
- resolution: {integrity: sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-roving-focus@1.1.11':
- resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-scroll-area@1.2.10':
- resolution: {integrity: sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-select@2.2.6':
- resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-separator@1.1.8':
- resolution: {integrity: sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-slot@1.2.3':
- resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-slot@1.2.4':
- resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-switch@1.2.6':
- resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-tabs@1.1.13':
- resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-toast@1.2.15':
- resolution: {integrity: sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-tooltip@1.2.8':
- resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/react-use-callback-ref@1.1.1':
- resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-use-controllable-state@1.2.2':
- resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-use-effect-event@0.0.2':
- resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-use-escape-keydown@1.1.1':
- resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-use-layout-effect@1.1.1':
- resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-use-previous@1.1.1':
- resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-use-rect@1.1.1':
- resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-use-size@1.1.1':
- resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- '@radix-ui/react-visually-hidden@1.2.3':
- resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==}
- peerDependencies:
- '@types/react': '*'
- '@types/react-dom': '*'
- react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@radix-ui/rect@1.1.1':
- resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==}
-
- '@rolldown/pluginutils@1.0.0-beta.53':
- resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==}
-
- '@rollup/rollup-android-arm-eabi@4.53.5':
- resolution: {integrity: sha512-iDGS/h7D8t7tvZ1t6+WPK04KD0MwzLZrG0se1hzBjSi5fyxlsiggoJHwh18PCFNn7tG43OWb6pdZ6Y+rMlmyNQ==}
- cpu: [arm]
- os: [android]
-
- '@rollup/rollup-android-arm64@4.53.5':
- resolution: {integrity: sha512-wrSAViWvZHBMMlWk6EJhvg8/rjxzyEhEdgfMMjREHEq11EtJ6IP6yfcCH57YAEca2Oe3FNCE9DSTgU70EIGmVw==}
- cpu: [arm64]
- os: [android]
-
- '@rollup/rollup-darwin-arm64@4.53.5':
- resolution: {integrity: sha512-S87zZPBmRO6u1YXQLwpveZm4JfPpAa6oHBX7/ghSiGH3rz/KDgAu1rKdGutV+WUI6tKDMbaBJomhnT30Y2t4VQ==}
- cpu: [arm64]
- os: [darwin]
-
- '@rollup/rollup-darwin-x64@4.53.5':
- resolution: {integrity: sha512-YTbnsAaHo6VrAczISxgpTva8EkfQus0VPEVJCEaboHtZRIb6h6j0BNxRBOwnDciFTZLDPW5r+ZBmhL/+YpTZgA==}
- cpu: [x64]
- os: [darwin]
-
- '@rollup/rollup-freebsd-arm64@4.53.5':
- resolution: {integrity: sha512-1T8eY2J8rKJWzaznV7zedfdhD1BqVs1iqILhmHDq/bqCUZsrMt+j8VCTHhP0vdfbHK3e1IQ7VYx3jlKqwlf+vw==}
- cpu: [arm64]
- os: [freebsd]
-
- '@rollup/rollup-freebsd-x64@4.53.5':
- resolution: {integrity: sha512-sHTiuXyBJApxRn+VFMaw1U+Qsz4kcNlxQ742snICYPrY+DDL8/ZbaC4DVIB7vgZmp3jiDaKA0WpBdP0aqPJoBQ==}
- cpu: [x64]
- os: [freebsd]
-
- '@rollup/rollup-linux-arm-gnueabihf@4.53.5':
- resolution: {integrity: sha512-dV3T9MyAf0w8zPVLVBptVlzaXxka6xg1f16VAQmjg+4KMSTWDvhimI/Y6mp8oHwNrmnmVl9XxJ/w/mO4uIQONA==}
- cpu: [arm]
- os: [linux]
-
- '@rollup/rollup-linux-arm-musleabihf@4.53.5':
- resolution: {integrity: sha512-wIGYC1x/hyjP+KAu9+ewDI+fi5XSNiUi9Bvg6KGAh2TsNMA3tSEs+Sh6jJ/r4BV/bx/CyWu2ue9kDnIdRyafcQ==}
- cpu: [arm]
- os: [linux]
-
- '@rollup/rollup-linux-arm64-gnu@4.53.5':
- resolution: {integrity: sha512-Y+qVA0D9d0y2FRNiG9oM3Hut/DgODZbU9I8pLLPwAsU0tUKZ49cyV1tzmB/qRbSzGvY8lpgGkJuMyuhH7Ma+Vg==}
- cpu: [arm64]
- os: [linux]
-
- '@rollup/rollup-linux-arm64-musl@4.53.5':
- resolution: {integrity: sha512-juaC4bEgJsyFVfqhtGLz8mbopaWD+WeSOYr5E16y+1of6KQjc0BpwZLuxkClqY1i8sco+MdyoXPNiCkQou09+g==}
- cpu: [arm64]
- os: [linux]
-
- '@rollup/rollup-linux-loong64-gnu@4.53.5':
- resolution: {integrity: sha512-rIEC0hZ17A42iXtHX+EPJVL/CakHo+tT7W0pbzdAGuWOt2jxDFh7A/lRhsNHBcqL4T36+UiAgwO8pbmn3dE8wA==}
- cpu: [loong64]
- os: [linux]
-
- '@rollup/rollup-linux-ppc64-gnu@4.53.5':
- resolution: {integrity: sha512-T7l409NhUE552RcAOcmJHj3xyZ2h7vMWzcwQI0hvn5tqHh3oSoclf9WgTl+0QqffWFG8MEVZZP1/OBglKZx52Q==}
- cpu: [ppc64]
- os: [linux]
-
- '@rollup/rollup-linux-riscv64-gnu@4.53.5':
- resolution: {integrity: sha512-7OK5/GhxbnrMcxIFoYfhV/TkknarkYC1hqUw1wU2xUN3TVRLNT5FmBv4KkheSG2xZ6IEbRAhTooTV2+R5Tk0lQ==}
- cpu: [riscv64]
- os: [linux]
-
- '@rollup/rollup-linux-riscv64-musl@4.53.5':
- resolution: {integrity: sha512-GwuDBE/PsXaTa76lO5eLJTyr2k8QkPipAyOrs4V/KJufHCZBJ495VCGJol35grx9xryk4V+2zd3Ri+3v7NPh+w==}
- cpu: [riscv64]
- os: [linux]
-
- '@rollup/rollup-linux-s390x-gnu@4.53.5':
- resolution: {integrity: sha512-IAE1Ziyr1qNfnmiQLHBURAD+eh/zH1pIeJjeShleII7Vj8kyEm2PF77o+lf3WTHDpNJcu4IXJxNO0Zluro8bOw==}
- cpu: [s390x]
- os: [linux]
-
- '@rollup/rollup-linux-x64-gnu@4.53.5':
- resolution: {integrity: sha512-Pg6E+oP7GvZ4XwgRJBuSXZjcqpIW3yCBhK4BcsANvb47qMvAbCjR6E+1a/U2WXz1JJxp9/4Dno3/iSJLcm5auw==}
- cpu: [x64]
- os: [linux]
-
- '@rollup/rollup-linux-x64-musl@4.53.5':
- resolution: {integrity: sha512-txGtluxDKTxaMDzUduGP0wdfng24y1rygUMnmlUJ88fzCCULCLn7oE5kb2+tRB+MWq1QDZT6ObT5RrR8HFRKqg==}
- cpu: [x64]
- os: [linux]
-
- '@rollup/rollup-openharmony-arm64@4.53.5':
- resolution: {integrity: sha512-3DFiLPnTxiOQV993fMc+KO8zXHTcIjgaInrqlG8zDp1TlhYl6WgrOHuJkJQ6M8zHEcntSJsUp1XFZSY8C1DYbg==}
- cpu: [arm64]
- os: [openharmony]
-
- '@rollup/rollup-win32-arm64-msvc@4.53.5':
- resolution: {integrity: sha512-nggc/wPpNTgjGg75hu+Q/3i32R00Lq1B6N1DO7MCU340MRKL3WZJMjA9U4K4gzy3dkZPXm9E1Nc81FItBVGRlA==}
- cpu: [arm64]
- os: [win32]
-
- '@rollup/rollup-win32-ia32-msvc@4.53.5':
- resolution: {integrity: sha512-U/54pTbdQpPLBdEzCT6NBCFAfSZMvmjr0twhnD9f4EIvlm9wy3jjQ38yQj1AGznrNO65EWQMgm/QUjuIVrYF9w==}
- cpu: [ia32]
- os: [win32]
-
- '@rollup/rollup-win32-x64-gnu@4.53.5':
- resolution: {integrity: sha512-2NqKgZSuLH9SXBBV2dWNRCZmocgSOx8OJSdpRaEcRlIfX8YrKxUT6z0F1NpvDVhOsl190UFTRh2F2WDWWCYp3A==}
- cpu: [x64]
- os: [win32]
-
- '@rollup/rollup-win32-x64-msvc@4.53.5':
- resolution: {integrity: sha512-JRpZUhCfhZ4keB5v0fe02gQJy05GqboPOaxvjugW04RLSYYoB/9t2lx2u/tMs/Na/1NXfY8QYjgRljRpN+MjTQ==}
- cpu: [x64]
- os: [win32]
-
- '@sindresorhus/is@4.6.0':
- resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
- engines: {node: '>=10'}
-
- '@standard-schema/spec@1.1.0':
- resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
-
- '@szmarczak/http-timer@4.0.6':
- resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
- engines: {node: '>=10'}
-
- '@tailwindcss/node@4.1.18':
- resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==}
-
- '@tailwindcss/oxide-android-arm64@4.1.18':
- resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [android]
-
- '@tailwindcss/oxide-darwin-arm64@4.1.18':
- resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [darwin]
-
- '@tailwindcss/oxide-darwin-x64@4.1.18':
- resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [darwin]
-
- '@tailwindcss/oxide-freebsd-x64@4.1.18':
- resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [freebsd]
-
- '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18':
- resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==}
- engines: {node: '>= 10'}
- cpu: [arm]
- os: [linux]
-
- '@tailwindcss/oxide-linux-arm64-gnu@4.1.18':
- resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [linux]
-
- '@tailwindcss/oxide-linux-arm64-musl@4.1.18':
- resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [linux]
-
- '@tailwindcss/oxide-linux-x64-gnu@4.1.18':
- resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [linux]
-
- '@tailwindcss/oxide-linux-x64-musl@4.1.18':
- resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [linux]
-
- '@tailwindcss/oxide-wasm32-wasi@4.1.18':
- resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==}
- engines: {node: '>=14.0.0'}
- cpu: [wasm32]
- bundledDependencies:
- - '@napi-rs/wasm-runtime'
- - '@emnapi/core'
- - '@emnapi/runtime'
- - '@tybys/wasm-util'
- - '@emnapi/wasi-threads'
- - tslib
-
- '@tailwindcss/oxide-win32-arm64-msvc@4.1.18':
- resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [win32]
-
- '@tailwindcss/oxide-win32-x64-msvc@4.1.18':
- resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [win32]
-
- '@tailwindcss/oxide@4.1.18':
- resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==}
- engines: {node: '>= 10'}
-
- '@tailwindcss/postcss@4.1.18':
- resolution: {integrity: sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==}
-
- '@tailwindcss/typography@0.5.19':
- resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==}
- peerDependencies:
- tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
-
- '@tanstack/react-virtual@3.13.13':
- resolution: {integrity: sha512-4o6oPMDvQv+9gMi8rE6gWmsOjtUZUYIJHv7EB+GblyYdi8U6OqLl8rhHWIUZSL1dUU2dPwTdTgybCKf9EjIrQg==}
- peerDependencies:
- react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
- react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
-
- '@tanstack/virtual-core@3.13.13':
- resolution: {integrity: sha512-uQFoSdKKf5S8k51W5t7b2qpfkyIbdHMzAn+AMQvHPxKUPeo1SsGaA4JRISQT87jm28b7z8OEqPcg1IOZagQHcA==}
-
- '@testing-library/dom@10.4.1':
- resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
- engines: {node: '>=18'}
-
- '@testing-library/react@16.3.1':
- resolution: {integrity: sha512-gr4KtAWqIOQoucWYD/f6ki+j5chXfcPc74Col/6poTyqTmn7zRmodWahWRCp8tYd+GMqBonw6hstNzqjbs6gjw==}
- engines: {node: '>=18'}
- peerDependencies:
- '@testing-library/dom': ^10.0.0
- '@types/react': ^18.0.0 || ^19.0.0
- '@types/react-dom': ^18.0.0 || ^19.0.0
- react: ^18.0.0 || ^19.0.0
- react-dom: ^18.0.0 || ^19.0.0
- peerDependenciesMeta:
- '@types/react':
- optional: true
- '@types/react-dom':
- optional: true
-
- '@tootallnate/once@2.0.0':
- resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
- engines: {node: '>= 10'}
-
- '@types/aria-query@5.0.4':
- resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
-
- '@types/babel__core@7.20.5':
- resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
-
- '@types/babel__generator@7.27.0':
- resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
-
- '@types/babel__template@7.4.4':
- resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
-
- '@types/babel__traverse@7.28.0':
- resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
-
- '@types/cacheable-request@6.0.3':
- resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==}
-
- '@types/chai@5.2.3':
- resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
-
- '@types/debug@4.1.12':
- resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
-
- '@types/deep-eql@4.0.2':
- resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
-
- '@types/estree-jsx@1.0.5':
- resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
-
- '@types/estree@1.0.8':
- resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
-
- '@types/fs-extra@9.0.13':
- resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==}
-
- '@types/hast@3.0.4':
- resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
-
- '@types/http-cache-semantics@4.0.4':
- resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==}
-
- '@types/json-schema@7.0.15':
- resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
-
- '@types/keyv@3.1.4':
- resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
-
- '@types/mdast@4.0.4':
- resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
-
- '@types/ms@2.1.0':
- resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
-
- '@types/node@22.19.3':
- resolution: {integrity: sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==}
-
- '@types/node@25.0.3':
- resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==}
-
- '@types/plist@3.0.5':
- resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==}
-
- '@types/react-dom@19.2.3':
- resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
- peerDependencies:
- '@types/react': ^19.2.0
-
- '@types/react@19.2.7':
- resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==}
-
- '@types/responselike@1.0.3':
- resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==}
-
- '@types/unist@2.0.11':
- resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
-
- '@types/unist@3.0.3':
- resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
-
- '@types/uuid@10.0.0':
- resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==}
-
- '@types/verror@1.10.11':
- resolution: {integrity: sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==}
-
- '@types/yauzl@2.10.3':
- resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
-
- '@typescript-eslint/eslint-plugin@8.50.0':
- resolution: {integrity: sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- '@typescript-eslint/parser': ^8.50.0
- eslint: ^8.57.0 || ^9.0.0
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/parser@8.50.0':
- resolution: {integrity: sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/project-service@8.50.0':
- resolution: {integrity: sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/scope-manager@8.50.0':
- resolution: {integrity: sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@typescript-eslint/tsconfig-utils@8.50.0':
- resolution: {integrity: sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/type-utils@8.50.0':
- resolution: {integrity: sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/types@8.50.0':
- resolution: {integrity: sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@typescript-eslint/typescript-estree@8.50.0':
- resolution: {integrity: sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/utils@8.50.0':
- resolution: {integrity: sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/visitor-keys@8.50.0':
- resolution: {integrity: sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@ungap/structured-clone@1.3.0':
- resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
-
- '@vitejs/plugin-react@5.1.2':
- resolution: {integrity: sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==}
- engines: {node: ^20.19.0 || >=22.12.0}
- peerDependencies:
- vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
-
- '@vitest/expect@4.0.16':
- resolution: {integrity: sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==}
-
- '@vitest/mocker@4.0.16':
- resolution: {integrity: sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg==}
- peerDependencies:
- msw: ^2.4.9
- vite: ^6.0.0 || ^7.0.0-0
- peerDependenciesMeta:
- msw:
- optional: true
- vite:
- optional: true
-
- '@vitest/pretty-format@4.0.16':
- resolution: {integrity: sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA==}
-
- '@vitest/runner@4.0.16':
- resolution: {integrity: sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q==}
-
- '@vitest/snapshot@4.0.16':
- resolution: {integrity: sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA==}
-
- '@vitest/spy@4.0.16':
- resolution: {integrity: sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw==}
-
- '@vitest/utils@4.0.16':
- resolution: {integrity: sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==}
-
- '@xmldom/xmldom@0.8.11':
- resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==}
- engines: {node: '>=10.0.0'}
-
- '@xterm/addon-fit@0.10.0':
- resolution: {integrity: sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==}
- peerDependencies:
- '@xterm/xterm': ^5.0.0
-
- '@xterm/addon-serialize@0.13.0':
- resolution: {integrity: sha512-kGs8o6LWAmN1l2NpMp01/YkpxbmO4UrfWybeGu79Khw5K9+Krp7XhXbBTOTc3GJRRhd6EmILjpR8k5+odY39YQ==}
- peerDependencies:
- '@xterm/xterm': ^5.0.0
-
- '@xterm/addon-web-links@0.11.0':
- resolution: {integrity: sha512-nIHQ38pQI+a5kXnRaTgwqSHnX7KE6+4SVoceompgHL26unAxdfP6IPqUTSYPQgSwM56hsElfoNrrW5V7BUED/Q==}
- peerDependencies:
- '@xterm/xterm': ^5.0.0
-
- '@xterm/addon-webgl@0.18.0':
- resolution: {integrity: sha512-xCnfMBTI+/HKPdRnSOHaJDRqEpq2Ugy8LEj9GiY4J3zJObo3joylIFaMvzBwbYRg8zLtkO0KQaStCeSfoaI2/w==}
- peerDependencies:
- '@xterm/xterm': ^5.0.0
-
- '@xterm/xterm@5.5.0':
- resolution: {integrity: sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==}
-
- abbrev@1.1.1:
- resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
-
- acorn-jsx@5.3.2:
- resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
- peerDependencies:
- acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
-
- acorn@8.15.0:
- resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
- engines: {node: '>=0.4.0'}
- hasBin: true
-
- agent-base@6.0.2:
- resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
- engines: {node: '>= 6.0.0'}
-
- agent-base@7.1.4:
- resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
- engines: {node: '>= 14'}
-
- agentkeepalive@4.6.0:
- resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==}
- engines: {node: '>= 8.0.0'}
-
- aggregate-error@3.1.0:
- resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
- engines: {node: '>=8'}
-
- ajv-keywords@3.5.2:
- resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==}
- peerDependencies:
- ajv: ^6.9.1
-
- ajv@6.12.6:
- resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
-
- ansi-escapes@7.2.0:
- resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==}
- engines: {node: '>=18'}
-
- ansi-regex@5.0.1:
- resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
- engines: {node: '>=8'}
-
- ansi-regex@6.2.2:
- resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
- engines: {node: '>=12'}
-
- ansi-styles@4.3.0:
- resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
- engines: {node: '>=8'}
-
- ansi-styles@5.2.0:
- resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
- engines: {node: '>=10'}
-
- ansi-styles@6.2.3:
- resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
- engines: {node: '>=12'}
-
- app-builder-bin@5.0.0-alpha.12:
- resolution: {integrity: sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==}
-
- app-builder-lib@26.0.12:
- resolution: {integrity: sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==}
- engines: {node: '>=14.0.0'}
- peerDependencies:
- dmg-builder: ^26.0.12
- electron-builder-squirrel-windows: ^26.0.12
-
- argparse@2.0.1:
- resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
-
- aria-hidden@1.2.6:
- resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
- engines: {node: '>=10'}
-
- aria-query@5.3.0:
- resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
-
- array-buffer-byte-length@1.0.2:
- resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
- engines: {node: '>= 0.4'}
-
- array-includes@3.1.9:
- resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
- engines: {node: '>= 0.4'}
-
- array.prototype.findlast@1.2.5:
- resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==}
- engines: {node: '>= 0.4'}
-
- array.prototype.flat@1.3.3:
- resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==}
- engines: {node: '>= 0.4'}
-
- array.prototype.flatmap@1.3.3:
- resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==}
- engines: {node: '>= 0.4'}
-
- array.prototype.tosorted@1.1.4:
- resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==}
- engines: {node: '>= 0.4'}
-
- arraybuffer.prototype.slice@1.0.4:
- resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
- engines: {node: '>= 0.4'}
-
- assert-plus@1.0.0:
- resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==}
- engines: {node: '>=0.8'}
-
- assertion-error@2.0.1:
- resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
- engines: {node: '>=12'}
-
- astral-regex@2.0.0:
- resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
- engines: {node: '>=8'}
-
- async-exit-hook@2.0.1:
- resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==}
- engines: {node: '>=0.12.0'}
-
- async-function@1.0.0:
- resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
- engines: {node: '>= 0.4'}
-
- async@3.2.6:
- resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
-
- asynckit@0.4.0:
- resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
-
- at-least-node@1.0.0:
- resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
- engines: {node: '>= 4.0.0'}
-
- autoprefixer@10.4.23:
- resolution: {integrity: sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==}
- engines: {node: ^10 || ^12 || >=14}
- hasBin: true
- peerDependencies:
- postcss: ^8.1.0
-
- available-typed-arrays@1.0.7:
- resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
- engines: {node: '>= 0.4'}
-
- bail@2.0.2:
- resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
-
- balanced-match@1.0.2:
- resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
-
- base64-js@1.5.1:
- resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
-
- baseline-browser-mapping@2.9.10:
- resolution: {integrity: sha512-2VIKvDx8Z1a9rTB2eCkdPE5nSe28XnA+qivGnWHoB40hMMt/h1hSz0960Zqsn6ZyxWXUie0EBdElKv8may20AA==}
- hasBin: true
-
- bl@4.1.0:
- resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
-
- boolean@3.2.0:
- resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==}
- deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
-
- brace-expansion@1.1.12:
- resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
-
- brace-expansion@2.0.2:
- resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
-
- braces@3.0.3:
- resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
- engines: {node: '>=8'}
-
- browserslist@4.28.1:
- resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==}
- engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
- hasBin: true
-
- buffer-crc32@0.2.13:
- resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
-
- buffer-from@1.1.2:
- resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
-
- buffer@5.7.1:
- resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
-
- builder-util-runtime@9.3.1:
- resolution: {integrity: sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==}
- engines: {node: '>=12.0.0'}
-
- builder-util@26.0.11:
- resolution: {integrity: sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==}
-
- cac@6.7.14:
- resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
- engines: {node: '>=8'}
-
- cacache@16.1.3:
- resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==}
- engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
-
- cacheable-lookup@5.0.4:
- resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==}
- engines: {node: '>=10.6.0'}
-
- cacheable-request@7.0.4:
- resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==}
- engines: {node: '>=8'}
-
- call-bind-apply-helpers@1.0.2:
- resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
- engines: {node: '>= 0.4'}
-
- call-bind@1.0.8:
- resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
- engines: {node: '>= 0.4'}
-
- call-bound@1.0.4:
- resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
- engines: {node: '>= 0.4'}
-
- callsites@3.1.0:
- resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
- engines: {node: '>=6'}
-
- caniuse-lite@1.0.30001761:
- resolution: {integrity: sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==}
-
- ccount@2.0.1:
- resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
-
- chai@6.2.1:
- resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==}
- engines: {node: '>=18'}
-
- chalk@4.1.2:
- resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
- engines: {node: '>=10'}
-
- character-entities-html4@2.1.0:
- resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
-
- character-entities-legacy@3.0.0:
- resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
-
- character-entities@2.0.2:
- resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
-
- character-reference-invalid@2.0.1:
- resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
-
- chokidar@5.0.0:
- resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
- engines: {node: '>= 20.19.0'}
-
- chownr@2.0.0:
- resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
- engines: {node: '>=10'}
-
- chromium-pickle-js@0.2.0:
- resolution: {integrity: sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==}
-
- ci-info@3.9.0:
- resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
- engines: {node: '>=8'}
-
- class-variance-authority@0.7.1:
- resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
-
- clean-stack@2.2.0:
- resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
- engines: {node: '>=6'}
-
- cli-cursor@3.1.0:
- resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
- engines: {node: '>=8'}
-
- cli-cursor@5.0.0:
- resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==}
- engines: {node: '>=18'}
-
- cli-spinners@2.9.2:
- resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
- engines: {node: '>=6'}
-
- cli-truncate@2.1.0:
- resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==}
- engines: {node: '>=8'}
-
- cli-truncate@5.1.1:
- resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==}
- engines: {node: '>=20'}
-
- cliui@8.0.1:
- resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
- engines: {node: '>=12'}
-
- clone-response@1.0.3:
- resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==}
-
- clone@1.0.4:
- resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
- engines: {node: '>=0.8'}
-
- clsx@2.1.1:
- resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
- engines: {node: '>=6'}
-
- color-convert@2.0.1:
- resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
- engines: {node: '>=7.0.0'}
-
- color-name@1.1.4:
- resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
-
- colorette@2.0.20:
- resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
-
- combined-stream@1.0.8:
- resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
- engines: {node: '>= 0.8'}
-
- comma-separated-tokens@2.0.3:
- resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
-
- commander@14.0.2:
- resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==}
- engines: {node: '>=20'}
-
- commander@5.1.0:
- resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==}
- engines: {node: '>= 6'}
-
- commander@9.5.0:
- resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
- engines: {node: ^12.20.0 || >=14}
-
- compare-version@0.1.2:
- resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==}
- engines: {node: '>=0.10.0'}
-
- concat-map@0.0.1:
- resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
-
- config-file-ts@0.2.8-rc1:
- resolution: {integrity: sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==}
-
- convert-source-map@2.0.0:
- resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
-
- core-util-is@1.0.2:
- resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
-
- crc@3.8.0:
- resolution: {integrity: sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==}
-
- cross-dirname@0.1.0:
- resolution: {integrity: sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==}
-
- cross-spawn@7.0.6:
- resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
- engines: {node: '>= 8'}
-
- cssesc@3.0.0:
- resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
- engines: {node: '>=4'}
- hasBin: true
-
- cssstyle@4.6.0:
- resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==}
- engines: {node: '>=18'}
-
- csstype@3.2.3:
- resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
-
- data-urls@5.0.0:
- resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==}
- engines: {node: '>=18'}
-
- data-view-buffer@1.0.2:
- resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
- engines: {node: '>= 0.4'}
-
- data-view-byte-length@1.0.2:
- resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==}
- engines: {node: '>= 0.4'}
-
- data-view-byte-offset@1.0.1:
- resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
- engines: {node: '>= 0.4'}
-
- debug@4.4.3:
- resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
- engines: {node: '>=6.0'}
- peerDependencies:
- supports-color: '*'
- peerDependenciesMeta:
- supports-color:
- optional: true
-
- decimal.js@10.6.0:
- resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==}
-
- decode-named-character-reference@1.2.0:
- resolution: {integrity: sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==}
-
- decompress-response@6.0.0:
- resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
- engines: {node: '>=10'}
-
- deep-is@0.1.4:
- resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
-
- defaults@1.0.4:
- resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
-
- defer-to-connect@2.0.1:
- resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==}
- engines: {node: '>=10'}
-
- define-data-property@1.1.4:
- resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
- engines: {node: '>= 0.4'}
-
- define-properties@1.2.1:
- resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
- engines: {node: '>= 0.4'}
-
- delayed-stream@1.0.0:
- resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
- engines: {node: '>=0.4.0'}
-
- dequal@2.0.3:
- resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
- engines: {node: '>=6'}
-
- detect-libc@2.1.2:
- resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
- engines: {node: '>=8'}
-
- detect-node-es@1.1.0:
- resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
-
- detect-node@2.1.0:
- resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
-
- devlop@1.1.0:
- resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
-
- dir-compare@4.2.0:
- resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==}
-
- dmg-builder@26.0.12:
- resolution: {integrity: sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==}
-
- dmg-license@1.0.11:
- resolution: {integrity: sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==}
- engines: {node: '>=8'}
- os: [darwin]
- hasBin: true
-
- doctrine@2.1.0:
- resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
- engines: {node: '>=0.10.0'}
-
- dom-accessibility-api@0.5.16:
- resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
-
- dotenv-expand@11.0.7:
- resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==}
- engines: {node: '>=12'}
-
- dotenv@16.6.1:
- resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
- engines: {node: '>=12'}
-
- dunder-proto@1.0.1:
- resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
- engines: {node: '>= 0.4'}
-
- eastasianwidth@0.2.0:
- resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
-
- ejs@3.1.10:
- resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==}
- engines: {node: '>=0.10.0'}
- hasBin: true
-
- electron-builder-squirrel-windows@26.0.12:
- resolution: {integrity: sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==}
-
- electron-builder@26.0.12:
- resolution: {integrity: sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==}
- engines: {node: '>=14.0.0'}
- hasBin: true
-
- electron-publish@26.0.11:
- resolution: {integrity: sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==}
-
- electron-to-chromium@1.5.267:
- resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==}
-
- electron-updater@6.6.2:
- resolution: {integrity: sha512-Cr4GDOkbAUqRHP5/oeOmH/L2Bn6+FQPxVLZtPbcmKZC63a1F3uu5EefYOssgZXG3u/zBlubbJ5PJdITdMVggbw==}
-
- electron-vite@5.0.0:
- resolution: {integrity: sha512-OHp/vjdlubNlhNkPkL/+3JD34ii5ov7M0GpuXEVdQeqdQ3ulvVR7Dg/rNBLfS5XPIFwgoBLDf9sjjrL+CuDyRQ==}
- engines: {node: ^20.19.0 || >=22.12.0}
- hasBin: true
- peerDependencies:
- '@swc/core': ^1.0.0
- vite: ^5.0.0 || ^6.0.0 || ^7.0.0
- peerDependenciesMeta:
- '@swc/core':
- optional: true
-
- electron-winstaller@5.4.0:
- resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==}
- engines: {node: '>=8.0.0'}
-
- electron@39.2.7:
- resolution: {integrity: sha512-KU0uFS6LSTh4aOIC3miolcbizOFP7N1M46VTYVfqIgFiuA2ilfNaOHLDS9tCMvwwHRowAsvqBrh9NgMXcTOHCQ==}
- engines: {node: '>= 12.20.55'}
- hasBin: true
-
- emoji-regex@10.6.0:
- resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
-
- emoji-regex@8.0.0:
- resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
-
- emoji-regex@9.2.2:
- resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
-
- encoding@0.1.13:
- resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==}
-
- end-of-stream@1.4.5:
- resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
-
- enhanced-resolve@5.18.4:
- resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==}
- engines: {node: '>=10.13.0'}
-
- entities@6.0.1:
- resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
- engines: {node: '>=0.12'}
-
- env-paths@2.2.1:
- resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
- engines: {node: '>=6'}
-
- environment@1.1.0:
- resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==}
- engines: {node: '>=18'}
-
- err-code@2.0.3:
- resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==}
-
- es-abstract@1.24.1:
- resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==}
- engines: {node: '>= 0.4'}
-
- es-define-property@1.0.1:
- resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
- engines: {node: '>= 0.4'}
-
- es-errors@1.3.0:
- resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
- engines: {node: '>= 0.4'}
-
- es-iterator-helpers@1.2.2:
- resolution: {integrity: sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==}
- engines: {node: '>= 0.4'}
-
- es-module-lexer@1.7.0:
- resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
-
- es-object-atoms@1.1.1:
- resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
- engines: {node: '>= 0.4'}
-
- es-set-tostringtag@2.1.0:
- resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
- engines: {node: '>= 0.4'}
-
- es-shim-unscopables@1.1.0:
- resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==}
- engines: {node: '>= 0.4'}
-
- es-to-primitive@1.3.0:
- resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
- engines: {node: '>= 0.4'}
-
- es6-error@4.1.1:
- resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
-
- esbuild@0.25.12:
- resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
- engines: {node: '>=18'}
- hasBin: true
-
- esbuild@0.27.2:
- resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==}
- engines: {node: '>=18'}
- hasBin: true
-
- escalade@3.2.0:
- resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
- engines: {node: '>=6'}
-
- escape-string-regexp@4.0.0:
- resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
- engines: {node: '>=10'}
-
- escape-string-regexp@5.0.0:
- resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
- engines: {node: '>=12'}
-
- eslint-plugin-react-hooks@7.0.1:
- resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==}
- engines: {node: '>=18'}
- peerDependencies:
- eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
-
- eslint-plugin-react@7.37.5:
- resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==}
- engines: {node: '>=4'}
- peerDependencies:
- eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
-
- eslint-scope@8.4.0:
- resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- eslint-visitor-keys@3.4.3:
- resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
-
- eslint-visitor-keys@4.2.1:
- resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- eslint@9.39.2:
- resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- hasBin: true
- peerDependencies:
- jiti: '*'
- peerDependenciesMeta:
- jiti:
- optional: true
-
- espree@10.4.0:
- resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- esquery@1.6.0:
- resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
- engines: {node: '>=0.10'}
-
- esrecurse@4.3.0:
- resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
- engines: {node: '>=4.0'}
-
- estraverse@5.3.0:
- resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
- engines: {node: '>=4.0'}
-
- estree-util-is-identifier-name@3.0.0:
- resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
-
- estree-walker@3.0.3:
- resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
-
- esutils@2.0.3:
- resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
- engines: {node: '>=0.10.0'}
-
- eventemitter3@5.0.1:
- resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
-
- expect-type@1.3.0:
- resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
- engines: {node: '>=12.0.0'}
-
- exponential-backoff@3.1.3:
- resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==}
-
- extend@3.0.2:
- resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
-
- extract-zip@2.0.1:
- resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==}
- engines: {node: '>= 10.17.0'}
- hasBin: true
-
- extsprintf@1.4.1:
- resolution: {integrity: sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==}
- engines: {'0': node >=0.6.0}
-
- fast-deep-equal@3.1.3:
- resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
-
- fast-json-stable-stringify@2.1.0:
- resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
-
- fast-levenshtein@2.0.6:
- resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
-
- fd-slicer@1.1.0:
- resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
-
- fdir@6.5.0:
- resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
- engines: {node: '>=12.0.0'}
- peerDependencies:
- picomatch: ^3 || ^4
- peerDependenciesMeta:
- picomatch:
- optional: true
-
- file-entry-cache@8.0.0:
- resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
- engines: {node: '>=16.0.0'}
-
- filelist@1.0.4:
- resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
-
- fill-range@7.1.1:
- resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
- engines: {node: '>=8'}
-
- find-up@5.0.0:
- resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
- engines: {node: '>=10'}
-
- flat-cache@4.0.1:
- resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
- engines: {node: '>=16'}
-
- flatted@3.3.3:
- resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
-
- for-each@0.3.5:
- resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
- engines: {node: '>= 0.4'}
-
- foreground-child@3.3.1:
- resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
- engines: {node: '>=14'}
-
- form-data@4.0.5:
- resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==}
- engines: {node: '>= 6'}
-
- fraction.js@5.3.4:
- resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
-
- framer-motion@12.23.26:
- resolution: {integrity: sha512-cPcIhgR42xBn1Uj+PzOyheMtZ73H927+uWPDVhUMqxy8UHt6Okavb6xIz9J/phFUHUj0OncR6UvMfJTXoc/LKA==}
- peerDependencies:
- '@emotion/is-prop-valid': '*'
- react: ^18.0.0 || ^19.0.0
- react-dom: ^18.0.0 || ^19.0.0
- peerDependenciesMeta:
- '@emotion/is-prop-valid':
- optional: true
- react:
- optional: true
- react-dom:
- optional: true
-
- fs-extra@10.1.0:
- resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
- engines: {node: '>=12'}
-
- fs-extra@11.3.3:
- resolution: {integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==}
- engines: {node: '>=14.14'}
-
- fs-extra@7.0.1:
- resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==}
- engines: {node: '>=6 <7 || >=8'}
-
- fs-extra@8.1.0:
- resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==}
- engines: {node: '>=6 <7 || >=8'}
-
- fs-extra@9.1.0:
- resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
- engines: {node: '>=10'}
-
- fs-minipass@2.1.0:
- resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
- engines: {node: '>= 8'}
-
- fs.realpath@1.0.0:
- resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
-
- fsevents@2.3.2:
- resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
- engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
- os: [darwin]
-
- fsevents@2.3.3:
- resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
- engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
- os: [darwin]
-
- function-bind@1.1.2:
- resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
-
- function.prototype.name@1.1.8:
- resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==}
- engines: {node: '>= 0.4'}
-
- functions-have-names@1.2.3:
- resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
-
- generator-function@2.0.1:
- resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
- engines: {node: '>= 0.4'}
-
- gensync@1.0.0-beta.2:
- resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
- engines: {node: '>=6.9.0'}
-
- get-caller-file@2.0.5:
- resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
- engines: {node: 6.* || 8.* || >= 10.*}
-
- get-east-asian-width@1.4.0:
- resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==}
- engines: {node: '>=18'}
-
- get-intrinsic@1.3.0:
- resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
- engines: {node: '>= 0.4'}
-
- get-nonce@1.0.1:
- resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
- engines: {node: '>=6'}
-
- get-proto@1.0.1:
- resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
- engines: {node: '>= 0.4'}
-
- get-stream@5.2.0:
- resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
- engines: {node: '>=8'}
-
- get-symbol-description@1.1.0:
- resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
- engines: {node: '>= 0.4'}
-
- glob-parent@6.0.2:
- resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
- engines: {node: '>=10.13.0'}
-
- glob@10.5.0:
- resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==}
- hasBin: true
-
- glob@7.2.3:
- resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
- deprecated: Glob versions prior to v9 are no longer supported
-
- glob@8.1.0:
- resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
- engines: {node: '>=12'}
- deprecated: Glob versions prior to v9 are no longer supported
-
- global-agent@3.0.0:
- resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==}
- engines: {node: '>=10.0'}
-
- globals@14.0.0:
- resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
- engines: {node: '>=18'}
-
- globals@16.5.0:
- resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==}
- engines: {node: '>=18'}
-
- globalthis@1.0.4:
- resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
- engines: {node: '>= 0.4'}
-
- gopd@1.2.0:
- resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
- engines: {node: '>= 0.4'}
-
- got@11.8.6:
- resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==}
- engines: {node: '>=10.19.0'}
-
- graceful-fs@4.2.11:
- resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
-
- has-bigints@1.1.0:
- resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
- engines: {node: '>= 0.4'}
-
- has-flag@4.0.0:
- resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
- engines: {node: '>=8'}
-
- has-property-descriptors@1.0.2:
- resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
-
- has-proto@1.2.0:
- resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==}
- engines: {node: '>= 0.4'}
-
- has-symbols@1.1.0:
- resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
- engines: {node: '>= 0.4'}
-
- has-tostringtag@1.0.2:
- resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
- engines: {node: '>= 0.4'}
-
- hasown@2.0.2:
- resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
- engines: {node: '>= 0.4'}
-
- hast-util-to-jsx-runtime@2.3.6:
- resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
-
- hast-util-whitespace@3.0.0:
- resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
-
- hermes-estree@0.25.1:
- resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==}
-
- hermes-parser@0.25.1:
- resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
-
- hosted-git-info@4.1.0:
- resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==}
- engines: {node: '>=10'}
-
- html-encoding-sniffer@4.0.0:
- resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
- engines: {node: '>=18'}
-
- html-url-attributes@3.0.1:
- resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
-
- http-cache-semantics@4.2.0:
- resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
-
- http-proxy-agent@5.0.0:
- resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==}
- engines: {node: '>= 6'}
-
- http-proxy-agent@7.0.2:
- resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
- engines: {node: '>= 14'}
-
- http2-wrapper@1.0.3:
- resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==}
- engines: {node: '>=10.19.0'}
-
- https-proxy-agent@5.0.1:
- resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
- engines: {node: '>= 6'}
-
- https-proxy-agent@7.0.6:
- resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
- engines: {node: '>= 14'}
-
- humanize-ms@1.2.1:
- resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==}
-
- husky@9.1.7:
- resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==}
- engines: {node: '>=18'}
- hasBin: true
-
- iconv-corefoundation@1.1.7:
- resolution: {integrity: sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==}
- engines: {node: ^8.11.2 || >=10}
- os: [darwin]
-
- iconv-lite@0.6.3:
- resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
- engines: {node: '>=0.10.0'}
-
- ieee754@1.2.1:
- resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
-
- ignore@5.3.2:
- resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
- engines: {node: '>= 4'}
-
- ignore@7.0.5:
- resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
- engines: {node: '>= 4'}
-
- import-fresh@3.3.1:
- resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
- engines: {node: '>=6'}
-
- imurmurhash@0.1.4:
- resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
- engines: {node: '>=0.8.19'}
-
- indent-string@4.0.0:
- resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
- engines: {node: '>=8'}
-
- infer-owner@1.0.4:
- resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==}
-
- inflight@1.0.6:
- resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
- deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
-
- inherits@2.0.4:
- resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
-
- inline-style-parser@0.2.7:
- resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
-
- internal-slot@1.1.0:
- resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
- engines: {node: '>= 0.4'}
-
- ip-address@10.1.0:
- resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==}
- engines: {node: '>= 12'}
-
- is-alphabetical@2.0.1:
- resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
-
- is-alphanumerical@2.0.1:
- resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
-
- is-array-buffer@3.0.5:
- resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
- engines: {node: '>= 0.4'}
-
- is-async-function@2.1.1:
- resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==}
- engines: {node: '>= 0.4'}
-
- is-bigint@1.1.0:
- resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
- engines: {node: '>= 0.4'}
-
- is-boolean-object@1.2.2:
- resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
- engines: {node: '>= 0.4'}
-
- is-callable@1.2.7:
- resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
- engines: {node: '>= 0.4'}
-
- is-ci@3.0.1:
- resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==}
- hasBin: true
-
- is-core-module@2.16.1:
- resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
- engines: {node: '>= 0.4'}
-
- is-data-view@1.0.2:
- resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==}
- engines: {node: '>= 0.4'}
-
- is-date-object@1.1.0:
- resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
- engines: {node: '>= 0.4'}
-
- is-decimal@2.0.1:
- resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
-
- is-extglob@2.1.1:
- resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
- engines: {node: '>=0.10.0'}
-
- is-finalizationregistry@1.1.1:
- resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
- engines: {node: '>= 0.4'}
-
- is-fullwidth-code-point@3.0.0:
- resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
- engines: {node: '>=8'}
-
- is-fullwidth-code-point@5.1.0:
- resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==}
- engines: {node: '>=18'}
-
- is-generator-function@1.1.2:
- resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
- engines: {node: '>= 0.4'}
-
- is-glob@4.0.3:
- resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
- engines: {node: '>=0.10.0'}
-
- is-hexadecimal@2.0.1:
- resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
-
- is-interactive@1.0.0:
- resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
- engines: {node: '>=8'}
-
- is-lambda@1.0.1:
- resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==}
-
- is-map@2.0.3:
- resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
- engines: {node: '>= 0.4'}
-
- is-negative-zero@2.0.3:
- resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
- engines: {node: '>= 0.4'}
-
- is-number-object@1.1.1:
- resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
- engines: {node: '>= 0.4'}
-
- is-number@7.0.0:
- resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
- engines: {node: '>=0.12.0'}
-
- is-plain-obj@4.1.0:
- resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
- engines: {node: '>=12'}
-
- is-potential-custom-element-name@1.0.1:
- resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
-
- is-regex@1.2.1:
- resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
- engines: {node: '>= 0.4'}
-
- is-set@2.0.3:
- resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==}
- engines: {node: '>= 0.4'}
-
- is-shared-array-buffer@1.0.4:
- resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
- engines: {node: '>= 0.4'}
-
- is-string@1.1.1:
- resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
- engines: {node: '>= 0.4'}
-
- is-symbol@1.1.1:
- resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==}
- engines: {node: '>= 0.4'}
-
- is-typed-array@1.1.15:
- resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
- engines: {node: '>= 0.4'}
-
- is-unicode-supported@0.1.0:
- resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
- engines: {node: '>=10'}
-
- is-weakmap@2.0.2:
- resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
- engines: {node: '>= 0.4'}
-
- is-weakref@1.1.1:
- resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==}
- engines: {node: '>= 0.4'}
-
- is-weakset@2.0.4:
- resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
- engines: {node: '>= 0.4'}
-
- isarray@2.0.5:
- resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
-
- isbinaryfile@4.0.10:
- resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==}
- engines: {node: '>= 8.0.0'}
-
- isbinaryfile@5.0.7:
- resolution: {integrity: sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==}
- engines: {node: '>= 18.0.0'}
-
- isexe@2.0.0:
- resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
-
- iterator.prototype@1.1.5:
- resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
- engines: {node: '>= 0.4'}
-
- jackspeak@3.4.3:
- resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
-
- jake@10.9.4:
- resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==}
- engines: {node: '>=10'}
- hasBin: true
-
- jiti@2.6.1:
- resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
- hasBin: true
-
- js-tokens@4.0.0:
- resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
-
- js-yaml@4.1.1:
- resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
- hasBin: true
-
- jsdom@26.1.0:
- resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==}
- engines: {node: '>=18'}
- peerDependencies:
- canvas: ^3.0.0
- peerDependenciesMeta:
- canvas:
- optional: true
-
- jsesc@3.1.0:
- resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
- engines: {node: '>=6'}
- hasBin: true
-
- json-buffer@3.0.1:
- resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
-
- json-schema-traverse@0.4.1:
- resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
-
- json-stable-stringify-without-jsonify@1.0.1:
- resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
-
- json-stringify-safe@5.0.1:
- resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
-
- json5@2.2.3:
- resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
- engines: {node: '>=6'}
- hasBin: true
-
- jsonfile@4.0.0:
- resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
-
- jsonfile@6.2.0:
- resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==}
-
- jsx-ast-utils@3.3.5:
- resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
- engines: {node: '>=4.0'}
-
- keyv@4.5.4:
- resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
-
- lazy-val@1.0.5:
- resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==}
-
- levn@0.4.1:
- resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
- engines: {node: '>= 0.8.0'}
-
- lightningcss-android-arm64@1.30.2:
- resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [android]
-
- lightningcss-darwin-arm64@1.30.2:
- resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [darwin]
-
- lightningcss-darwin-x64@1.30.2:
- resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [darwin]
-
- lightningcss-freebsd-x64@1.30.2:
- resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [freebsd]
-
- lightningcss-linux-arm-gnueabihf@1.30.2:
- resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm]
- os: [linux]
-
- lightningcss-linux-arm64-gnu@1.30.2:
- resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [linux]
-
- lightningcss-linux-arm64-musl@1.30.2:
- resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [linux]
-
- lightningcss-linux-x64-gnu@1.30.2:
- resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [linux]
-
- lightningcss-linux-x64-musl@1.30.2:
- resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [linux]
-
- lightningcss-win32-arm64-msvc@1.30.2:
- resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
- engines: {node: '>= 12.0.0'}
- cpu: [arm64]
- os: [win32]
-
- lightningcss-win32-x64-msvc@1.30.2:
- resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==}
- engines: {node: '>= 12.0.0'}
- cpu: [x64]
- os: [win32]
-
- lightningcss@1.30.2:
- resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
- engines: {node: '>= 12.0.0'}
-
- lint-staged@16.2.7:
- resolution: {integrity: sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==}
- engines: {node: '>=20.17'}
- hasBin: true
-
- listr2@9.0.5:
- resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==}
- engines: {node: '>=20.0.0'}
-
- locate-path@6.0.0:
- resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
- engines: {node: '>=10'}
-
- lodash.escaperegexp@4.1.2:
- resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==}
-
- lodash.isequal@4.5.0:
- resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
- deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead.
-
- lodash.merge@4.6.2:
- resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
-
- lodash@4.17.21:
- resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
-
- log-symbols@4.1.0:
- resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
- engines: {node: '>=10'}
-
- log-update@6.1.0:
- resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
- engines: {node: '>=18'}
-
- longest-streak@3.1.0:
- resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
-
- loose-envify@1.4.0:
- resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
- hasBin: true
-
- lowercase-keys@2.0.0:
- resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==}
- engines: {node: '>=8'}
-
- lru-cache@10.4.3:
- resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
-
- lru-cache@5.1.1:
- resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
-
- lru-cache@6.0.0:
- resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
- engines: {node: '>=10'}
-
- lru-cache@7.18.3:
- resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
- engines: {node: '>=12'}
-
- lucide-react@0.560.0:
- resolution: {integrity: sha512-NwKoUA/aBShsdL8WE5lukV2F/tjHzQRlonQs7fkNGI1sCT0Ay4a9Ap3ST2clUUkcY+9eQ0pBe2hybTQd2fmyDA==}
- peerDependencies:
- react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
-
- lz-string@1.5.0:
- resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
- hasBin: true
-
- magic-string@0.30.21:
- resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
-
- make-fetch-happen@10.2.1:
- resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==}
- engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
-
- markdown-table@3.0.4:
- resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
-
- matcher@3.0.0:
- resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==}
- engines: {node: '>=10'}
-
- math-intrinsics@1.1.0:
- resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
- engines: {node: '>= 0.4'}
-
- mdast-util-find-and-replace@3.0.2:
- resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
-
- mdast-util-from-markdown@2.0.2:
- resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==}
-
- mdast-util-gfm-autolink-literal@2.0.1:
- resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}
-
- mdast-util-gfm-footnote@2.1.0:
- resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==}
-
- mdast-util-gfm-strikethrough@2.0.0:
- resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
-
- mdast-util-gfm-table@2.0.0:
- resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
-
- mdast-util-gfm-task-list-item@2.0.0:
- resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
-
- mdast-util-gfm@3.1.0:
- resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==}
-
- mdast-util-mdx-expression@2.0.1:
- resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
-
- mdast-util-mdx-jsx@3.2.0:
- resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
-
- mdast-util-mdxjs-esm@2.0.1:
- resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
-
- mdast-util-phrasing@4.1.0:
- resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
-
- mdast-util-to-hast@13.2.1:
- resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}
-
- mdast-util-to-markdown@2.1.2:
- resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
-
- mdast-util-to-string@4.0.0:
- resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
-
- micromark-core-commonmark@2.0.3:
- resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
-
- micromark-extension-gfm-autolink-literal@2.1.0:
- resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==}
-
- micromark-extension-gfm-footnote@2.1.0:
- resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==}
-
- micromark-extension-gfm-strikethrough@2.1.0:
- resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==}
-
- micromark-extension-gfm-table@2.1.1:
- resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==}
-
- micromark-extension-gfm-tagfilter@2.0.0:
- resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
-
- micromark-extension-gfm-task-list-item@2.1.0:
- resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==}
-
- micromark-extension-gfm@3.0.0:
- resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
-
- micromark-factory-destination@2.0.1:
- resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
-
- micromark-factory-label@2.0.1:
- resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
-
- micromark-factory-space@2.0.1:
- resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
-
- micromark-factory-title@2.0.1:
- resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==}
-
- micromark-factory-whitespace@2.0.1:
- resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==}
-
- micromark-util-character@2.1.1:
- resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
-
- micromark-util-chunked@2.0.1:
- resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==}
-
- micromark-util-classify-character@2.0.1:
- resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==}
-
- micromark-util-combine-extensions@2.0.1:
- resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==}
-
- micromark-util-decode-numeric-character-reference@2.0.2:
- resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==}
-
- micromark-util-decode-string@2.0.1:
- resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==}
-
- micromark-util-encode@2.0.1:
- resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
-
- micromark-util-html-tag-name@2.0.1:
- resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
-
- micromark-util-normalize-identifier@2.0.1:
- resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==}
-
- micromark-util-resolve-all@2.0.1:
- resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==}
-
- micromark-util-sanitize-uri@2.0.1:
- resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
-
- micromark-util-subtokenize@2.1.0:
- resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==}
-
- micromark-util-symbol@2.0.1:
- resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
-
- micromark-util-types@2.0.2:
- resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
-
- micromark@4.0.2:
- resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
-
- micromatch@4.0.8:
- resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
- engines: {node: '>=8.6'}
-
- mime-db@1.52.0:
- resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
- engines: {node: '>= 0.6'}
-
- mime-types@2.1.35:
- resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
- engines: {node: '>= 0.6'}
-
- mime@2.6.0:
- resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==}
- engines: {node: '>=4.0.0'}
- hasBin: true
-
- mimic-fn@2.1.0:
- resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
- engines: {node: '>=6'}
-
- mimic-function@5.0.1:
- resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
- engines: {node: '>=18'}
-
- mimic-response@1.0.1:
- resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==}
- engines: {node: '>=4'}
-
- mimic-response@3.1.0:
- resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
- engines: {node: '>=10'}
-
- minimatch@10.1.1:
- resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==}
- engines: {node: 20 || >=22}
-
- minimatch@3.1.2:
- resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
-
- minimatch@5.1.6:
- resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
- engines: {node: '>=10'}
-
- minimatch@9.0.5:
- resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
- engines: {node: '>=16 || 14 >=14.17'}
-
- minimist@1.2.8:
- resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
-
- minipass-collect@1.0.2:
- resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==}
- engines: {node: '>= 8'}
-
- minipass-fetch@2.1.2:
- resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==}
- engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
-
- minipass-flush@1.0.5:
- resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==}
- engines: {node: '>= 8'}
-
- minipass-pipeline@1.2.4:
- resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==}
- engines: {node: '>=8'}
-
- minipass-sized@1.0.3:
- resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==}
- engines: {node: '>=8'}
-
- minipass@3.3.6:
- resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
- engines: {node: '>=8'}
-
- minipass@5.0.0:
- resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
- engines: {node: '>=8'}
-
- minipass@7.1.2:
- resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
- engines: {node: '>=16 || 14 >=14.17'}
-
- minizlib@2.1.2:
- resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
- engines: {node: '>= 8'}
-
- mkdirp@0.5.6:
- resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
- hasBin: true
-
- mkdirp@1.0.4:
- resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
- engines: {node: '>=10'}
- hasBin: true
-
- motion-dom@12.23.23:
- resolution: {integrity: sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==}
-
- motion-utils@12.23.6:
- resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==}
-
- motion@12.23.26:
- resolution: {integrity: sha512-Ll8XhVxY8LXMVYTCfme27WH2GjBrCIzY4+ndr5QKxsK+YwCtOi2B/oBi5jcIbik5doXuWT/4KKDOVAZJkeY5VQ==}
- peerDependencies:
- '@emotion/is-prop-valid': '*'
- react: ^18.0.0 || ^19.0.0
- react-dom: ^18.0.0 || ^19.0.0
- peerDependenciesMeta:
- '@emotion/is-prop-valid':
- optional: true
- react:
- optional: true
- react-dom:
- optional: true
-
- ms@2.1.3:
- resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
-
- nano-spawn@2.0.0:
- resolution: {integrity: sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==}
- engines: {node: '>=20.17'}
-
- nanoid@3.3.11:
- resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
- engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
- hasBin: true
-
- natural-compare@1.4.0:
- resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
-
- negotiator@0.6.4:
- resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==}
- engines: {node: '>= 0.6'}
-
- node-abi@3.85.0:
- resolution: {integrity: sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==}
- engines: {node: '>=10'}
-
- node-addon-api@1.7.2:
- resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==}
-
- node-api-version@0.2.1:
- resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==}
-
- node-releases@2.0.27:
- resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
-
- nopt@6.0.0:
- resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==}
- engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
- hasBin: true
-
- normalize-url@6.1.0:
- resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==}
- engines: {node: '>=10'}
-
- nwsapi@2.2.23:
- resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==}
-
- object-assign@4.1.1:
- resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
- engines: {node: '>=0.10.0'}
-
- object-inspect@1.13.4:
- resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
- engines: {node: '>= 0.4'}
-
- object-keys@1.1.1:
- resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
- engines: {node: '>= 0.4'}
-
- object.assign@4.1.7:
- resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==}
- engines: {node: '>= 0.4'}
-
- object.entries@1.1.9:
- resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==}
- engines: {node: '>= 0.4'}
-
- object.fromentries@2.0.8:
- resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==}
- engines: {node: '>= 0.4'}
-
- object.values@1.2.1:
- resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
- engines: {node: '>= 0.4'}
-
- obug@2.1.1:
- resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
-
- once@1.4.0:
- resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
-
- onetime@5.1.2:
- resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
- engines: {node: '>=6'}
-
- onetime@7.0.0:
- resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
- engines: {node: '>=18'}
-
- optionator@0.9.4:
- resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
- engines: {node: '>= 0.8.0'}
-
- ora@5.4.1:
- resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==}
- engines: {node: '>=10'}
-
- own-keys@1.0.1:
- resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
- engines: {node: '>= 0.4'}
-
- p-cancelable@2.1.1:
- resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==}
- engines: {node: '>=8'}
-
- p-limit@3.1.0:
- resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
- engines: {node: '>=10'}
-
- p-locate@5.0.0:
- resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
- engines: {node: '>=10'}
-
- p-map@4.0.0:
- resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
- engines: {node: '>=10'}
-
- package-json-from-dist@1.0.1:
- resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
-
- parent-module@1.0.1:
- resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
- engines: {node: '>=6'}
-
- parse-entities@4.0.2:
- resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
-
- parse5@7.3.0:
- resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
-
- path-exists@4.0.0:
- resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
- engines: {node: '>=8'}
-
- path-is-absolute@1.0.1:
- resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
- engines: {node: '>=0.10.0'}
-
- path-key@3.1.1:
- resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
- engines: {node: '>=8'}
-
- path-parse@1.0.7:
- resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
-
- path-scurry@1.11.1:
- resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
- engines: {node: '>=16 || 14 >=14.18'}
-
- pathe@2.0.3:
- resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
-
- pe-library@0.4.1:
- resolution: {integrity: sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==}
- engines: {node: '>=12', npm: '>=6'}
-
- pend@1.2.0:
- resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
-
- picocolors@1.1.1:
- resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
-
- picomatch@2.3.1:
- resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
- engines: {node: '>=8.6'}
-
- picomatch@4.0.3:
- resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
- engines: {node: '>=12'}
-
- pidtree@0.6.0:
- resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==}
- engines: {node: '>=0.10'}
- hasBin: true
-
- playwright-core@1.57.0:
- resolution: {integrity: sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==}
- engines: {node: '>=18'}
- hasBin: true
-
- playwright@1.57.0:
- resolution: {integrity: sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==}
- engines: {node: '>=18'}
- hasBin: true
-
- plist@3.1.0:
- resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==}
- engines: {node: '>=10.4.0'}
-
- possible-typed-array-names@1.1.0:
- resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
- engines: {node: '>= 0.4'}
-
- postcss-selector-parser@6.0.10:
- resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
- engines: {node: '>=4'}
-
- postcss-value-parser@4.2.0:
- resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
-
- postcss@8.5.6:
- resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
- engines: {node: ^10 || ^12 || >=14}
-
- postject@1.0.0-alpha.6:
- resolution: {integrity: sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==}
- engines: {node: '>=14.0.0'}
- hasBin: true
-
- prelude-ls@1.2.1:
- resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
- engines: {node: '>= 0.8.0'}
-
- pretty-format@27.5.1:
- resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
- engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
-
- proc-log@2.0.1:
- resolution: {integrity: sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==}
- engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
-
- progress@2.0.3:
- resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
- engines: {node: '>=0.4.0'}
-
- promise-inflight@1.0.1:
- resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==}
- peerDependencies:
- bluebird: '*'
- peerDependenciesMeta:
- bluebird:
- optional: true
-
- promise-retry@2.0.1:
- resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==}
- engines: {node: '>=10'}
-
- prop-types@15.8.1:
- resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
-
- property-information@7.1.0:
- resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
-
- pump@3.0.3:
- resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==}
-
- punycode@2.3.1:
- resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
- engines: {node: '>=6'}
-
- quick-lru@5.1.1:
- resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
- engines: {node: '>=10'}
-
- react-dom@19.2.3:
- resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==}
- peerDependencies:
- react: ^19.2.3
-
- react-is@16.13.1:
- resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
-
- react-is@17.0.2:
- resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
-
- react-markdown@10.1.0:
- resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==}
- peerDependencies:
- '@types/react': '>=18'
- react: '>=18'
-
- react-refresh@0.18.0:
- resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==}
- engines: {node: '>=0.10.0'}
-
- react-remove-scroll-bar@2.3.8:
- resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==}
- engines: {node: '>=10'}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- react-remove-scroll@2.7.2:
- resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==}
- engines: {node: '>=10'}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- react-resizable-panels@3.0.6:
- resolution: {integrity: sha512-b3qKHQ3MLqOgSS+FRYKapNkJZf5EQzuf6+RLiq1/IlTHw99YrZ2NJZLk4hQIzTnnIkRg2LUqyVinu6YWWpUYew==}
- peerDependencies:
- react: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
- react-dom: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
-
- react-style-singleton@2.2.3:
- resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
- engines: {node: '>=10'}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- react@19.2.3:
- resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
- engines: {node: '>=0.10.0'}
-
- read-binary-file-arch@1.0.6:
- resolution: {integrity: sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==}
- hasBin: true
-
- readable-stream@3.6.2:
- resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
- engines: {node: '>= 6'}
-
- readdirp@5.0.0:
- resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
- engines: {node: '>= 20.19.0'}
-
- reflect.getprototypeof@1.0.10:
- resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
- engines: {node: '>= 0.4'}
-
- regexp.prototype.flags@1.5.4:
- resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
- engines: {node: '>= 0.4'}
-
- remark-gfm@4.0.1:
- resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
-
- remark-parse@11.0.0:
- resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
-
- remark-rehype@11.1.2:
- resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
-
- remark-stringify@11.0.0:
- resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
-
- require-directory@2.1.1:
- resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
- engines: {node: '>=0.10.0'}
-
- resedit@1.7.2:
- resolution: {integrity: sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==}
- engines: {node: '>=12', npm: '>=6'}
-
- resolve-alpn@1.2.1:
- resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
-
- resolve-from@4.0.0:
- resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
- engines: {node: '>=4'}
-
- resolve@2.0.0-next.5:
- resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
- hasBin: true
-
- responselike@2.0.1:
- resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==}
-
- restore-cursor@3.1.0:
- resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
- engines: {node: '>=8'}
-
- restore-cursor@5.1.0:
- resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==}
- engines: {node: '>=18'}
-
- retry@0.12.0:
- resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
- engines: {node: '>= 4'}
-
- rfdc@1.4.1:
- resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
-
- rimraf@2.6.3:
- resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==}
- deprecated: Rimraf versions prior to v4 are no longer supported
- hasBin: true
-
- rimraf@3.0.2:
- resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
- deprecated: Rimraf versions prior to v4 are no longer supported
- hasBin: true
-
- roarr@2.15.4:
- resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==}
- engines: {node: '>=8.0'}
-
- rollup@4.53.5:
- resolution: {integrity: sha512-iTNAbFSlRpcHeeWu73ywU/8KuU/LZmNCSxp6fjQkJBD3ivUb8tpDrXhIxEzA05HlYMEwmtaUnb3RP+YNv162OQ==}
- engines: {node: '>=18.0.0', npm: '>=8.0.0'}
- hasBin: true
-
- rrweb-cssom@0.8.0:
- resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==}
-
- safe-array-concat@1.1.3:
- resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
- engines: {node: '>=0.4'}
-
- safe-buffer@5.2.1:
- resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
-
- safe-push-apply@1.0.0:
- resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
- engines: {node: '>= 0.4'}
-
- safe-regex-test@1.1.0:
- resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
- engines: {node: '>= 0.4'}
-
- safer-buffer@2.1.2:
- resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
-
- sanitize-filename@1.6.3:
- resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==}
-
- sax@1.4.3:
- resolution: {integrity: sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==}
-
- saxes@6.0.0:
- resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
- engines: {node: '>=v12.22.7'}
-
- scheduler@0.27.0:
- resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
-
- semver-compare@1.0.0:
- resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==}
-
- semver@5.7.2:
- resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
- hasBin: true
-
- semver@6.3.1:
- resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
- hasBin: true
-
- semver@7.7.3:
- resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
- engines: {node: '>=10'}
- hasBin: true
-
- serialize-error@7.0.1:
- resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
- engines: {node: '>=10'}
-
- set-function-length@1.2.2:
- resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
- engines: {node: '>= 0.4'}
-
- set-function-name@2.0.2:
- resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
- engines: {node: '>= 0.4'}
-
- set-proto@1.0.0:
- resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
- engines: {node: '>= 0.4'}
-
- shebang-command@2.0.0:
- resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
- engines: {node: '>=8'}
-
- shebang-regex@3.0.0:
- resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
- engines: {node: '>=8'}
-
- side-channel-list@1.0.0:
- resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
- engines: {node: '>= 0.4'}
-
- side-channel-map@1.0.1:
- resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
- engines: {node: '>= 0.4'}
-
- side-channel-weakmap@1.0.2:
- resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
- engines: {node: '>= 0.4'}
-
- side-channel@1.1.0:
- resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
- engines: {node: '>= 0.4'}
-
- siginfo@2.0.0:
- resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
-
- signal-exit@3.0.7:
- resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
-
- signal-exit@4.1.0:
- resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
- engines: {node: '>=14'}
-
- simple-update-notifier@2.0.0:
- resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==}
- engines: {node: '>=10'}
-
- slice-ansi@3.0.0:
- resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==}
- engines: {node: '>=8'}
-
- slice-ansi@7.1.2:
- resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==}
- engines: {node: '>=18'}
-
- smart-buffer@4.2.0:
- resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
- engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
-
- socks-proxy-agent@7.0.0:
- resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==}
- engines: {node: '>= 10'}
-
- socks@2.8.7:
- resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==}
- engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
-
- source-map-js@1.2.1:
- resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
- engines: {node: '>=0.10.0'}
-
- source-map-support@0.5.21:
- resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
-
- source-map@0.6.1:
- resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
- engines: {node: '>=0.10.0'}
-
- space-separated-tokens@2.0.2:
- resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
-
- sprintf-js@1.1.3:
- resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
-
- ssri@9.0.1:
- resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==}
- engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
-
- stackback@0.0.2:
- resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
-
- stat-mode@1.0.0:
- resolution: {integrity: sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==}
- engines: {node: '>= 6'}
-
- std-env@3.10.0:
- resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
-
- stop-iteration-iterator@1.1.0:
- resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
- engines: {node: '>= 0.4'}
-
- string-argv@0.3.2:
- resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
- engines: {node: '>=0.6.19'}
-
- string-width@4.2.3:
- resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
- engines: {node: '>=8'}
-
- string-width@5.1.2:
- resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
- engines: {node: '>=12'}
-
- string-width@7.2.0:
- resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
- engines: {node: '>=18'}
-
- string-width@8.1.0:
- resolution: {integrity: sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==}
- engines: {node: '>=20'}
-
- string.prototype.matchall@4.0.12:
- resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==}
- engines: {node: '>= 0.4'}
-
- string.prototype.repeat@1.0.0:
- resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==}
-
- string.prototype.trim@1.2.10:
- resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==}
- engines: {node: '>= 0.4'}
-
- string.prototype.trimend@1.0.9:
- resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==}
- engines: {node: '>= 0.4'}
-
- string.prototype.trimstart@1.0.8:
- resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
- engines: {node: '>= 0.4'}
-
- string_decoder@1.3.0:
- resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
-
- stringify-entities@4.0.4:
- resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
-
- strip-ansi@6.0.1:
- resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
- engines: {node: '>=8'}
-
- strip-ansi@7.1.2:
- resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
- engines: {node: '>=12'}
-
- strip-json-comments@3.1.1:
- resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
- engines: {node: '>=8'}
-
- style-to-js@1.1.21:
- resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==}
-
- style-to-object@1.0.14:
- resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
-
- sumchecker@3.0.1:
- resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==}
- engines: {node: '>= 8.0'}
-
- supports-color@7.2.0:
- resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
- engines: {node: '>=8'}
-
- supports-preserve-symlinks-flag@1.0.0:
- resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
- engines: {node: '>= 0.4'}
-
- symbol-tree@3.2.4:
- resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
-
- tailwind-merge@3.4.0:
- resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==}
-
- tailwindcss@4.1.18:
- resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==}
-
- tapable@2.3.0:
- resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
- engines: {node: '>=6'}
-
- tar@6.2.1:
- resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
- engines: {node: '>=10'}
-
- temp-file@3.4.0:
- resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==}
-
- temp@0.9.4:
- resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==}
- engines: {node: '>=6.0.0'}
-
- tiny-async-pool@1.3.0:
- resolution: {integrity: sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==}
-
- tiny-typed-emitter@2.1.0:
- resolution: {integrity: sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==}
-
- tinybench@2.9.0:
- resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
-
- tinyexec@1.0.2:
- resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==}
- engines: {node: '>=18'}
-
- tinyglobby@0.2.15:
- resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
- engines: {node: '>=12.0.0'}
-
- tinyrainbow@3.0.3:
- resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==}
- engines: {node: '>=14.0.0'}
-
- tldts-core@6.1.86:
- resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==}
-
- tldts@6.1.86:
- resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==}
- hasBin: true
-
- tmp-promise@3.0.3:
- resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==}
-
- tmp@0.2.5:
- resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==}
- engines: {node: '>=14.14'}
-
- to-regex-range@5.0.1:
- resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
- engines: {node: '>=8.0'}
-
- tough-cookie@5.1.2:
- resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==}
- engines: {node: '>=16'}
-
- tr46@5.1.1:
- resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
- engines: {node: '>=18'}
-
- trim-lines@3.0.1:
- resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
-
- trough@2.2.0:
- resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
-
- truncate-utf8-bytes@1.0.2:
- resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==}
-
- ts-api-utils@2.1.0:
- resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
- engines: {node: '>=18.12'}
- peerDependencies:
- typescript: '>=4.8.4'
-
- tslib@2.8.1:
- resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
-
- type-check@0.4.0:
- resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
- engines: {node: '>= 0.8.0'}
-
- type-fest@0.13.1:
- resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
- engines: {node: '>=10'}
-
- typed-array-buffer@1.0.3:
- resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
- engines: {node: '>= 0.4'}
-
- typed-array-byte-length@1.0.3:
- resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==}
- engines: {node: '>= 0.4'}
-
- typed-array-byte-offset@1.0.4:
- resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==}
- engines: {node: '>= 0.4'}
-
- typed-array-length@1.0.7:
- resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
- engines: {node: '>= 0.4'}
-
- typescript-eslint@8.50.0:
- resolution: {integrity: sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '>=4.8.4 <6.0.0'
-
- typescript@5.9.3:
- resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
- engines: {node: '>=14.17'}
- hasBin: true
-
- unbox-primitive@1.1.0:
- resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
- engines: {node: '>= 0.4'}
-
- undici-types@6.21.0:
- resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
-
- undici-types@7.16.0:
- resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
-
- unified@11.0.5:
- resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
-
- unique-filename@2.0.1:
- resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==}
- engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
-
- unique-slug@3.0.0:
- resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==}
- engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
-
- unist-util-is@6.0.1:
- resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
-
- unist-util-position@5.0.0:
- resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
-
- unist-util-stringify-position@4.0.0:
- resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
-
- unist-util-visit-parents@6.0.2:
- resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
-
- unist-util-visit@5.0.0:
- resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
-
- universalify@0.1.2:
- resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
- engines: {node: '>= 4.0.0'}
-
- universalify@2.0.1:
- resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
- engines: {node: '>= 10.0.0'}
-
- update-browserslist-db@1.2.3:
- resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
- hasBin: true
- peerDependencies:
- browserslist: '>= 4.21.0'
-
- uri-js@4.4.1:
- resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
-
- use-callback-ref@1.3.3:
- resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
- engines: {node: '>=10'}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- use-sidecar@1.1.3:
- resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==}
- engines: {node: '>=10'}
- peerDependencies:
- '@types/react': '*'
- react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
- utf8-byte-length@1.0.5:
- resolution: {integrity: sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==}
-
- util-deprecate@1.0.2:
- resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
-
- uuid@13.0.0:
- resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==}
- hasBin: true
-
- verror@1.10.1:
- resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==}
- engines: {node: '>=0.6.0'}
-
- vfile-message@4.0.3:
- resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
-
- vfile@6.0.3:
- resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
-
- vite@7.3.0:
- resolution: {integrity: sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==}
- engines: {node: ^20.19.0 || >=22.12.0}
- hasBin: true
- peerDependencies:
- '@types/node': ^20.19.0 || >=22.12.0
- jiti: '>=1.21.0'
- less: ^4.0.0
- lightningcss: ^1.21.0
- sass: ^1.70.0
- sass-embedded: ^1.70.0
- stylus: '>=0.54.8'
- sugarss: ^5.0.0
- terser: ^5.16.0
- tsx: ^4.8.1
- yaml: ^2.4.2
- peerDependenciesMeta:
- '@types/node':
- optional: true
- jiti:
- optional: true
- less:
- optional: true
- lightningcss:
- optional: true
- sass:
- optional: true
- sass-embedded:
- optional: true
- stylus:
- optional: true
- sugarss:
- optional: true
- terser:
- optional: true
- tsx:
- optional: true
- yaml:
- optional: true
-
- vitest@4.0.16:
- resolution: {integrity: sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==}
- engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
- hasBin: true
- peerDependencies:
- '@edge-runtime/vm': '*'
- '@opentelemetry/api': ^1.9.0
- '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
- '@vitest/browser-playwright': 4.0.16
- '@vitest/browser-preview': 4.0.16
- '@vitest/browser-webdriverio': 4.0.16
- '@vitest/ui': 4.0.16
- happy-dom: '*'
- jsdom: '*'
- peerDependenciesMeta:
- '@edge-runtime/vm':
- optional: true
- '@opentelemetry/api':
- optional: true
- '@types/node':
- optional: true
- '@vitest/browser-playwright':
- optional: true
- '@vitest/browser-preview':
- optional: true
- '@vitest/browser-webdriverio':
- optional: true
- '@vitest/ui':
- optional: true
- happy-dom:
- optional: true
- jsdom:
- optional: true
-
- w3c-xmlserializer@5.0.0:
- resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
- engines: {node: '>=18'}
-
- wcwidth@1.0.1:
- resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
-
- webidl-conversions@7.0.0:
- resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
- engines: {node: '>=12'}
-
- whatwg-encoding@3.1.1:
- resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
- engines: {node: '>=18'}
-
- whatwg-mimetype@4.0.0:
- resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
- engines: {node: '>=18'}
-
- whatwg-url@14.2.0:
- resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==}
- engines: {node: '>=18'}
-
- which-boxed-primitive@1.1.1:
- resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
- engines: {node: '>= 0.4'}
-
- which-builtin-type@1.2.1:
- resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
- engines: {node: '>= 0.4'}
-
- which-collection@1.0.2:
- resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==}
- engines: {node: '>= 0.4'}
-
- which-typed-array@1.1.19:
- resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==}
- engines: {node: '>= 0.4'}
-
- which@2.0.2:
- resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
- engines: {node: '>= 8'}
- hasBin: true
-
- why-is-node-running@2.3.0:
- resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
- engines: {node: '>=8'}
- hasBin: true
-
- word-wrap@1.2.5:
- resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
- engines: {node: '>=0.10.0'}
-
- wrap-ansi@7.0.0:
- resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
- engines: {node: '>=10'}
-
- wrap-ansi@8.1.0:
- resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
- engines: {node: '>=12'}
-
- wrap-ansi@9.0.2:
- resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
- engines: {node: '>=18'}
-
- wrappy@1.0.2:
- resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
-
- ws@8.18.3:
- resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
- engines: {node: '>=10.0.0'}
- peerDependencies:
- bufferutil: ^4.0.1
- utf-8-validate: '>=5.0.2'
- peerDependenciesMeta:
- bufferutil:
- optional: true
- utf-8-validate:
- optional: true
-
- xml-name-validator@5.0.0:
- resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
- engines: {node: '>=18'}
-
- xmlbuilder@15.1.1:
- resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==}
- engines: {node: '>=8.0'}
-
- xmlchars@2.2.0:
- resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
-
- y18n@5.0.8:
- resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
- engines: {node: '>=10'}
-
- yallist@3.1.1:
- resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
-
- yallist@4.0.0:
- resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
-
- yaml@2.8.2:
- resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==}
- engines: {node: '>= 14.6'}
- hasBin: true
-
- yargs-parser@21.1.1:
- resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
- engines: {node: '>=12'}
-
- yargs@17.7.2:
- resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
- engines: {node: '>=12'}
-
- yauzl@2.10.0:
- resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==}
-
- yocto-queue@0.1.0:
- resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
- engines: {node: '>=10'}
-
- zod-validation-error@4.0.2:
- resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==}
- engines: {node: '>=18.0.0'}
- peerDependencies:
- zod: ^3.25.0 || ^4.0.0
-
- zod@4.2.1:
- resolution: {integrity: sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==}
-
- zustand@5.0.9:
- resolution: {integrity: sha512-ALBtUj0AfjJt3uNRQoL1tL2tMvj6Gp/6e39dnfT6uzpelGru8v1tPOGBzayOWbPJvujM8JojDk3E1LxeFisBNg==}
- engines: {node: '>=12.20.0'}
- peerDependencies:
- '@types/react': '>=18.0.0'
- immer: '>=9.0.6'
- react: '>=18.0.0'
- use-sync-external-store: '>=1.2.0'
- peerDependenciesMeta:
- '@types/react':
- optional: true
- immer:
- optional: true
- react:
- optional: true
- use-sync-external-store:
- optional: true
-
- zwitch@2.0.4:
- resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
-
-snapshots:
-
- 7zip-bin@5.2.0: {}
-
- '@alloc/quick-lru@5.2.0': {}
-
- '@asamuzakjp/css-color@3.2.0':
- dependencies:
- '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
- '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
- '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
- '@csstools/css-tokenizer': 3.0.4
- lru-cache: 10.4.3
-
- '@babel/code-frame@7.27.1':
- dependencies:
- '@babel/helper-validator-identifier': 7.28.5
- js-tokens: 4.0.0
- picocolors: 1.1.1
-
- '@babel/compat-data@7.28.5': {}
-
- '@babel/core@7.28.5':
- dependencies:
- '@babel/code-frame': 7.27.1
- '@babel/generator': 7.28.5
- '@babel/helper-compilation-targets': 7.27.2
- '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5)
- '@babel/helpers': 7.28.4
- '@babel/parser': 7.28.5
- '@babel/template': 7.27.2
- '@babel/traverse': 7.28.5
- '@babel/types': 7.28.5
- '@jridgewell/remapping': 2.3.5
- convert-source-map: 2.0.0
- debug: 4.4.3
- gensync: 1.0.0-beta.2
- json5: 2.2.3
- semver: 6.3.1
- transitivePeerDependencies:
- - supports-color
-
- '@babel/generator@7.28.5':
- dependencies:
- '@babel/parser': 7.28.5
- '@babel/types': 7.28.5
- '@jridgewell/gen-mapping': 0.3.13
- '@jridgewell/trace-mapping': 0.3.31
- jsesc: 3.1.0
-
- '@babel/helper-compilation-targets@7.27.2':
- dependencies:
- '@babel/compat-data': 7.28.5
- '@babel/helper-validator-option': 7.27.1
- browserslist: 4.28.1
- lru-cache: 5.1.1
- semver: 6.3.1
-
- '@babel/helper-globals@7.28.0': {}
-
- '@babel/helper-module-imports@7.27.1':
- dependencies:
- '@babel/traverse': 7.28.5
- '@babel/types': 7.28.5
- transitivePeerDependencies:
- - supports-color
-
- '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)':
- dependencies:
- '@babel/core': 7.28.5
- '@babel/helper-module-imports': 7.27.1
- '@babel/helper-validator-identifier': 7.28.5
- '@babel/traverse': 7.28.5
- transitivePeerDependencies:
- - supports-color
-
- '@babel/helper-plugin-utils@7.27.1': {}
-
- '@babel/helper-string-parser@7.27.1': {}
-
- '@babel/helper-validator-identifier@7.28.5': {}
-
- '@babel/helper-validator-option@7.27.1': {}
-
- '@babel/helpers@7.28.4':
- dependencies:
- '@babel/template': 7.27.2
- '@babel/types': 7.28.5
-
- '@babel/parser@7.28.5':
- dependencies:
- '@babel/types': 7.28.5
-
- '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.5)':
- dependencies:
- '@babel/core': 7.28.5
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)':
- dependencies:
- '@babel/core': 7.28.5
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)':
- dependencies:
- '@babel/core': 7.28.5
- '@babel/helper-plugin-utils': 7.27.1
-
- '@babel/runtime@7.28.4': {}
-
- '@babel/template@7.27.2':
- dependencies:
- '@babel/code-frame': 7.27.1
- '@babel/parser': 7.28.5
- '@babel/types': 7.28.5
-
- '@babel/traverse@7.28.5':
- dependencies:
- '@babel/code-frame': 7.27.1
- '@babel/generator': 7.28.5
- '@babel/helper-globals': 7.28.0
- '@babel/parser': 7.28.5
- '@babel/template': 7.27.2
- '@babel/types': 7.28.5
- debug: 4.4.3
- transitivePeerDependencies:
- - supports-color
-
- '@babel/types@7.28.5':
- dependencies:
- '@babel/helper-string-parser': 7.27.1
- '@babel/helper-validator-identifier': 7.28.5
-
- '@csstools/color-helpers@5.1.0': {}
-
- '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
- dependencies:
- '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
- '@csstools/css-tokenizer': 3.0.4
-
- '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
- dependencies:
- '@csstools/color-helpers': 5.1.0
- '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
- '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
- '@csstools/css-tokenizer': 3.0.4
-
- '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)':
- dependencies:
- '@csstools/css-tokenizer': 3.0.4
-
- '@csstools/css-tokenizer@3.0.4': {}
-
- '@develar/schema-utils@2.6.5':
- dependencies:
- ajv: 6.12.6
- ajv-keywords: 3.5.2(ajv@6.12.6)
-
- '@dnd-kit/accessibility@3.1.1(react@19.2.3)':
- dependencies:
- react: 19.2.3
- tslib: 2.8.1
-
- '@dnd-kit/core@6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@dnd-kit/accessibility': 3.1.1(react@19.2.3)
- '@dnd-kit/utilities': 3.2.2(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- tslib: 2.8.1
-
- '@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@dnd-kit/core': 6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@dnd-kit/utilities': 3.2.2(react@19.2.3)
- react: 19.2.3
- tslib: 2.8.1
-
- '@dnd-kit/utilities@3.2.2(react@19.2.3)':
- dependencies:
- react: 19.2.3
- tslib: 2.8.1
-
- '@electron-toolkit/preload@3.0.2(electron@39.2.7)':
- dependencies:
- electron: 39.2.7
-
- '@electron-toolkit/utils@4.0.0(electron@39.2.7)':
- dependencies:
- electron: 39.2.7
-
- '@electron/asar@3.2.18':
- dependencies:
- commander: 5.1.0
- glob: 7.2.3
- minimatch: 3.1.2
-
- '@electron/asar@3.4.1':
- dependencies:
- commander: 5.1.0
- glob: 7.2.3
- minimatch: 3.1.2
-
- '@electron/fuses@1.8.0':
- dependencies:
- chalk: 4.1.2
- fs-extra: 9.1.0
- minimist: 1.2.8
-
- '@electron/get@2.0.3':
- dependencies:
- debug: 4.4.3
- env-paths: 2.2.1
- fs-extra: 8.1.0
- got: 11.8.6
- progress: 2.0.3
- semver: 6.3.1
- sumchecker: 3.0.1
- optionalDependencies:
- global-agent: 3.0.0
- transitivePeerDependencies:
- - supports-color
-
- '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2':
- dependencies:
- env-paths: 2.2.1
- exponential-backoff: 3.1.3
- glob: 8.1.0
- graceful-fs: 4.2.11
- make-fetch-happen: 10.2.1
- nopt: 6.0.0
- proc-log: 2.0.1
- semver: 7.7.3
- tar: 6.2.1
- which: 2.0.2
- transitivePeerDependencies:
- - bluebird
- - supports-color
-
- '@electron/notarize@2.5.0':
- dependencies:
- debug: 4.4.3
- fs-extra: 9.1.0
- promise-retry: 2.0.1
- transitivePeerDependencies:
- - supports-color
-
- '@electron/osx-sign@1.3.1':
- dependencies:
- compare-version: 0.1.2
- debug: 4.4.3
- fs-extra: 10.1.0
- isbinaryfile: 4.0.10
- minimist: 1.2.8
- plist: 3.1.0
- transitivePeerDependencies:
- - supports-color
-
- '@electron/rebuild@3.7.0':
- dependencies:
- '@electron/node-gyp': https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2
- '@malept/cross-spawn-promise': 2.0.0
- chalk: 4.1.2
- debug: 4.4.3
- detect-libc: 2.1.2
- fs-extra: 10.1.0
- got: 11.8.6
- node-abi: 3.85.0
- node-api-version: 0.2.1
- ora: 5.4.1
- read-binary-file-arch: 1.0.6
- semver: 7.7.3
- tar: 6.2.1
- yargs: 17.7.2
- transitivePeerDependencies:
- - bluebird
- - supports-color
-
- '@electron/rebuild@3.7.2':
- dependencies:
- '@electron/node-gyp': https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2
- '@malept/cross-spawn-promise': 2.0.0
- chalk: 4.1.2
- debug: 4.4.3
- detect-libc: 2.1.2
- fs-extra: 10.1.0
- got: 11.8.6
- node-abi: 3.85.0
- node-api-version: 0.2.1
- ora: 5.4.1
- read-binary-file-arch: 1.0.6
- semver: 7.7.3
- tar: 6.2.1
- yargs: 17.7.2
- transitivePeerDependencies:
- - bluebird
- - supports-color
-
- '@electron/universal@2.0.1':
- dependencies:
- '@electron/asar': 3.2.18
- '@malept/cross-spawn-promise': 2.0.0
- debug: 4.4.3
- dir-compare: 4.2.0
- fs-extra: 11.3.3
- minimatch: 9.0.5
- plist: 3.1.0
- transitivePeerDependencies:
- - supports-color
-
- '@electron/windows-sign@1.2.2':
- dependencies:
- cross-dirname: 0.1.0
- debug: 4.4.3
- fs-extra: 11.3.3
- minimist: 1.2.8
- postject: 1.0.0-alpha.6
- transitivePeerDependencies:
- - supports-color
- optional: true
-
- '@esbuild/aix-ppc64@0.25.12':
- optional: true
-
- '@esbuild/aix-ppc64@0.27.2':
- optional: true
-
- '@esbuild/android-arm64@0.25.12':
- optional: true
-
- '@esbuild/android-arm64@0.27.2':
- optional: true
-
- '@esbuild/android-arm@0.25.12':
- optional: true
-
- '@esbuild/android-arm@0.27.2':
- optional: true
-
- '@esbuild/android-x64@0.25.12':
- optional: true
-
- '@esbuild/android-x64@0.27.2':
- optional: true
-
- '@esbuild/darwin-arm64@0.25.12':
- optional: true
-
- '@esbuild/darwin-arm64@0.27.2':
- optional: true
-
- '@esbuild/darwin-x64@0.25.12':
- optional: true
-
- '@esbuild/darwin-x64@0.27.2':
- optional: true
-
- '@esbuild/freebsd-arm64@0.25.12':
- optional: true
-
- '@esbuild/freebsd-arm64@0.27.2':
- optional: true
-
- '@esbuild/freebsd-x64@0.25.12':
- optional: true
-
- '@esbuild/freebsd-x64@0.27.2':
- optional: true
-
- '@esbuild/linux-arm64@0.25.12':
- optional: true
-
- '@esbuild/linux-arm64@0.27.2':
- optional: true
-
- '@esbuild/linux-arm@0.25.12':
- optional: true
-
- '@esbuild/linux-arm@0.27.2':
- optional: true
-
- '@esbuild/linux-ia32@0.25.12':
- optional: true
-
- '@esbuild/linux-ia32@0.27.2':
- optional: true
-
- '@esbuild/linux-loong64@0.25.12':
- optional: true
-
- '@esbuild/linux-loong64@0.27.2':
- optional: true
-
- '@esbuild/linux-mips64el@0.25.12':
- optional: true
-
- '@esbuild/linux-mips64el@0.27.2':
- optional: true
-
- '@esbuild/linux-ppc64@0.25.12':
- optional: true
-
- '@esbuild/linux-ppc64@0.27.2':
- optional: true
-
- '@esbuild/linux-riscv64@0.25.12':
- optional: true
-
- '@esbuild/linux-riscv64@0.27.2':
- optional: true
-
- '@esbuild/linux-s390x@0.25.12':
- optional: true
-
- '@esbuild/linux-s390x@0.27.2':
- optional: true
-
- '@esbuild/linux-x64@0.25.12':
- optional: true
-
- '@esbuild/linux-x64@0.27.2':
- optional: true
-
- '@esbuild/netbsd-arm64@0.25.12':
- optional: true
-
- '@esbuild/netbsd-arm64@0.27.2':
- optional: true
-
- '@esbuild/netbsd-x64@0.25.12':
- optional: true
-
- '@esbuild/netbsd-x64@0.27.2':
- optional: true
-
- '@esbuild/openbsd-arm64@0.25.12':
- optional: true
-
- '@esbuild/openbsd-arm64@0.27.2':
- optional: true
-
- '@esbuild/openbsd-x64@0.25.12':
- optional: true
-
- '@esbuild/openbsd-x64@0.27.2':
- optional: true
-
- '@esbuild/openharmony-arm64@0.25.12':
- optional: true
-
- '@esbuild/openharmony-arm64@0.27.2':
- optional: true
-
- '@esbuild/sunos-x64@0.25.12':
- optional: true
-
- '@esbuild/sunos-x64@0.27.2':
- optional: true
-
- '@esbuild/win32-arm64@0.25.12':
- optional: true
-
- '@esbuild/win32-arm64@0.27.2':
- optional: true
-
- '@esbuild/win32-ia32@0.25.12':
- optional: true
-
- '@esbuild/win32-ia32@0.27.2':
- optional: true
-
- '@esbuild/win32-x64@0.25.12':
- optional: true
-
- '@esbuild/win32-x64@0.27.2':
- optional: true
-
- '@eslint-community/eslint-utils@4.9.0(eslint@9.39.2(jiti@2.6.1))':
- dependencies:
- eslint: 9.39.2(jiti@2.6.1)
- eslint-visitor-keys: 3.4.3
-
- '@eslint-community/regexpp@4.12.2': {}
-
- '@eslint/config-array@0.21.1':
- dependencies:
- '@eslint/object-schema': 2.1.7
- debug: 4.4.3
- minimatch: 3.1.2
- transitivePeerDependencies:
- - supports-color
-
- '@eslint/config-helpers@0.4.2':
- dependencies:
- '@eslint/core': 0.17.0
-
- '@eslint/core@0.17.0':
- dependencies:
- '@types/json-schema': 7.0.15
-
- '@eslint/eslintrc@3.3.3':
- dependencies:
- ajv: 6.12.6
- debug: 4.4.3
- espree: 10.4.0
- globals: 14.0.0
- ignore: 5.3.2
- import-fresh: 3.3.1
- js-yaml: 4.1.1
- minimatch: 3.1.2
- strip-json-comments: 3.1.1
- transitivePeerDependencies:
- - supports-color
-
- '@eslint/js@9.39.2': {}
-
- '@eslint/object-schema@2.1.7': {}
-
- '@eslint/plugin-kit@0.4.1':
- dependencies:
- '@eslint/core': 0.17.0
- levn: 0.4.1
-
- '@floating-ui/core@1.7.3':
- dependencies:
- '@floating-ui/utils': 0.2.10
-
- '@floating-ui/dom@1.7.4':
- dependencies:
- '@floating-ui/core': 1.7.3
- '@floating-ui/utils': 0.2.10
-
- '@floating-ui/react-dom@2.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@floating-ui/dom': 1.7.4
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
-
- '@floating-ui/utils@0.2.10': {}
-
- '@gar/promisify@1.1.3': {}
-
- '@humanfs/core@0.19.1': {}
-
- '@humanfs/node@0.16.7':
- dependencies:
- '@humanfs/core': 0.19.1
- '@humanwhocodes/retry': 0.4.3
-
- '@humanwhocodes/module-importer@1.0.1': {}
-
- '@humanwhocodes/retry@0.4.3': {}
-
- '@isaacs/balanced-match@4.0.1': {}
-
- '@isaacs/brace-expansion@5.0.0':
- dependencies:
- '@isaacs/balanced-match': 4.0.1
-
- '@isaacs/cliui@8.0.2':
- dependencies:
- string-width: 5.1.2
- string-width-cjs: string-width@4.2.3
- strip-ansi: 7.1.2
- strip-ansi-cjs: strip-ansi@6.0.1
- wrap-ansi: 8.1.0
- wrap-ansi-cjs: wrap-ansi@7.0.0
-
- '@jridgewell/gen-mapping@0.3.13':
- dependencies:
- '@jridgewell/sourcemap-codec': 1.5.5
- '@jridgewell/trace-mapping': 0.3.31
-
- '@jridgewell/remapping@2.3.5':
- dependencies:
- '@jridgewell/gen-mapping': 0.3.13
- '@jridgewell/trace-mapping': 0.3.31
-
- '@jridgewell/resolve-uri@3.1.2': {}
-
- '@jridgewell/sourcemap-codec@1.5.5': {}
-
- '@jridgewell/trace-mapping@0.3.31':
- dependencies:
- '@jridgewell/resolve-uri': 3.1.2
- '@jridgewell/sourcemap-codec': 1.5.5
-
- '@lydell/node-pty-darwin-arm64@1.1.0':
- optional: true
-
- '@lydell/node-pty-darwin-x64@1.1.0':
- optional: true
-
- '@lydell/node-pty-linux-arm64@1.1.0':
- optional: true
-
- '@lydell/node-pty-linux-x64@1.1.0':
- optional: true
-
- '@lydell/node-pty-win32-arm64@1.1.0':
- optional: true
-
- '@lydell/node-pty-win32-x64@1.1.0':
- optional: true
-
- '@lydell/node-pty@1.1.0':
- optionalDependencies:
- '@lydell/node-pty-darwin-arm64': 1.1.0
- '@lydell/node-pty-darwin-x64': 1.1.0
- '@lydell/node-pty-linux-arm64': 1.1.0
- '@lydell/node-pty-linux-x64': 1.1.0
- '@lydell/node-pty-win32-arm64': 1.1.0
- '@lydell/node-pty-win32-x64': 1.1.0
-
- '@malept/cross-spawn-promise@2.0.0':
- dependencies:
- cross-spawn: 7.0.6
-
- '@malept/flatpak-bundler@0.4.0':
- dependencies:
- debug: 4.4.3
- fs-extra: 9.1.0
- lodash: 4.17.21
- tmp-promise: 3.0.3
- transitivePeerDependencies:
- - supports-color
-
- '@npmcli/fs@2.1.2':
- dependencies:
- '@gar/promisify': 1.1.3
- semver: 7.7.3
-
- '@npmcli/move-file@2.0.1':
- dependencies:
- mkdirp: 1.0.4
- rimraf: 3.0.2
-
- '@pkgjs/parseargs@0.11.0':
- optional: true
-
- '@playwright/test@1.57.0':
- dependencies:
- playwright: 1.57.0
-
- '@radix-ui/number@1.1.1': {}
-
- '@radix-ui/primitive@1.1.3': {}
-
- '@radix-ui/react-alert-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-context@1.1.2(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-context@1.1.3(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3)
- aria-hidden: 1.2.6
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- react-remove-scroll: 2.7.2(@types/react@19.2.7)(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-direction@1.1.1(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-id@1.1.1(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- aria-hidden: 1.2.6
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- react-remove-scroll: 2.7.2(@types/react@19.2.7)(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@floating-ui/react-dom': 2.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/rect': 1.1.1
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/react-slot': 1.2.4(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-progress@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/react-context': 1.1.3(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-radio-group@1.3.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/number': 1.1.1
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-select@2.2.6(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/number': 1.1.1
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- aria-hidden: 1.2.6
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- react-remove-scroll: 2.7.2(@types/react@19.2.7)(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-separator@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-slot@1.2.3(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-slot@1.2.4(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-switch@1.2.6(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-toast@1.2.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/primitive': 1.1.3
- '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.7)(react@19.2.3)
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-use-previous@1.1.1(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- '@radix-ui/rect': 1.1.1
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-use-size@1.1.1(@types/react@19.2.7)(react@19.2.3)':
- dependencies:
- '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
- react: 19.2.3
- optionalDependencies:
- '@types/react': 19.2.7
-
- '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@radix-ui/rect@1.1.1': {}
-
- '@rolldown/pluginutils@1.0.0-beta.53': {}
-
- '@rollup/rollup-android-arm-eabi@4.53.5':
- optional: true
-
- '@rollup/rollup-android-arm64@4.53.5':
- optional: true
-
- '@rollup/rollup-darwin-arm64@4.53.5':
- optional: true
-
- '@rollup/rollup-darwin-x64@4.53.5':
- optional: true
-
- '@rollup/rollup-freebsd-arm64@4.53.5':
- optional: true
-
- '@rollup/rollup-freebsd-x64@4.53.5':
- optional: true
-
- '@rollup/rollup-linux-arm-gnueabihf@4.53.5':
- optional: true
-
- '@rollup/rollup-linux-arm-musleabihf@4.53.5':
- optional: true
-
- '@rollup/rollup-linux-arm64-gnu@4.53.5':
- optional: true
-
- '@rollup/rollup-linux-arm64-musl@4.53.5':
- optional: true
-
- '@rollup/rollup-linux-loong64-gnu@4.53.5':
- optional: true
-
- '@rollup/rollup-linux-ppc64-gnu@4.53.5':
- optional: true
-
- '@rollup/rollup-linux-riscv64-gnu@4.53.5':
- optional: true
-
- '@rollup/rollup-linux-riscv64-musl@4.53.5':
- optional: true
-
- '@rollup/rollup-linux-s390x-gnu@4.53.5':
- optional: true
-
- '@rollup/rollup-linux-x64-gnu@4.53.5':
- optional: true
-
- '@rollup/rollup-linux-x64-musl@4.53.5':
- optional: true
-
- '@rollup/rollup-openharmony-arm64@4.53.5':
- optional: true
-
- '@rollup/rollup-win32-arm64-msvc@4.53.5':
- optional: true
-
- '@rollup/rollup-win32-ia32-msvc@4.53.5':
- optional: true
-
- '@rollup/rollup-win32-x64-gnu@4.53.5':
- optional: true
-
- '@rollup/rollup-win32-x64-msvc@4.53.5':
- optional: true
-
- '@sindresorhus/is@4.6.0': {}
-
- '@standard-schema/spec@1.1.0': {}
-
- '@szmarczak/http-timer@4.0.6':
- dependencies:
- defer-to-connect: 2.0.1
-
- '@tailwindcss/node@4.1.18':
- dependencies:
- '@jridgewell/remapping': 2.3.5
- enhanced-resolve: 5.18.4
- jiti: 2.6.1
- lightningcss: 1.30.2
- magic-string: 0.30.21
- source-map-js: 1.2.1
- tailwindcss: 4.1.18
-
- '@tailwindcss/oxide-android-arm64@4.1.18':
- optional: true
-
- '@tailwindcss/oxide-darwin-arm64@4.1.18':
- optional: true
-
- '@tailwindcss/oxide-darwin-x64@4.1.18':
- optional: true
-
- '@tailwindcss/oxide-freebsd-x64@4.1.18':
- optional: true
-
- '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18':
- optional: true
-
- '@tailwindcss/oxide-linux-arm64-gnu@4.1.18':
- optional: true
-
- '@tailwindcss/oxide-linux-arm64-musl@4.1.18':
- optional: true
-
- '@tailwindcss/oxide-linux-x64-gnu@4.1.18':
- optional: true
-
- '@tailwindcss/oxide-linux-x64-musl@4.1.18':
- optional: true
-
- '@tailwindcss/oxide-wasm32-wasi@4.1.18':
- optional: true
-
- '@tailwindcss/oxide-win32-arm64-msvc@4.1.18':
- optional: true
-
- '@tailwindcss/oxide-win32-x64-msvc@4.1.18':
- optional: true
-
- '@tailwindcss/oxide@4.1.18':
- optionalDependencies:
- '@tailwindcss/oxide-android-arm64': 4.1.18
- '@tailwindcss/oxide-darwin-arm64': 4.1.18
- '@tailwindcss/oxide-darwin-x64': 4.1.18
- '@tailwindcss/oxide-freebsd-x64': 4.1.18
- '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18
- '@tailwindcss/oxide-linux-arm64-gnu': 4.1.18
- '@tailwindcss/oxide-linux-arm64-musl': 4.1.18
- '@tailwindcss/oxide-linux-x64-gnu': 4.1.18
- '@tailwindcss/oxide-linux-x64-musl': 4.1.18
- '@tailwindcss/oxide-wasm32-wasi': 4.1.18
- '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18
- '@tailwindcss/oxide-win32-x64-msvc': 4.1.18
-
- '@tailwindcss/postcss@4.1.18':
- dependencies:
- '@alloc/quick-lru': 5.2.0
- '@tailwindcss/node': 4.1.18
- '@tailwindcss/oxide': 4.1.18
- postcss: 8.5.6
- tailwindcss: 4.1.18
-
- '@tailwindcss/typography@0.5.19(tailwindcss@4.1.18)':
- dependencies:
- postcss-selector-parser: 6.0.10
- tailwindcss: 4.1.18
-
- '@tanstack/react-virtual@3.13.13(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@tanstack/virtual-core': 3.13.13
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
-
- '@tanstack/virtual-core@3.13.13': {}
-
- '@testing-library/dom@10.4.1':
- dependencies:
- '@babel/code-frame': 7.27.1
- '@babel/runtime': 7.28.4
- '@types/aria-query': 5.0.4
- aria-query: 5.3.0
- dom-accessibility-api: 0.5.16
- lz-string: 1.5.0
- picocolors: 1.1.1
- pretty-format: 27.5.1
-
- '@testing-library/react@16.3.1(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
- dependencies:
- '@babel/runtime': 7.28.4
- '@testing-library/dom': 10.4.1
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
- '@types/react-dom': 19.2.3(@types/react@19.2.7)
-
- '@tootallnate/once@2.0.0': {}
-
- '@types/aria-query@5.0.4': {}
-
- '@types/babel__core@7.20.5':
- dependencies:
- '@babel/parser': 7.28.5
- '@babel/types': 7.28.5
- '@types/babel__generator': 7.27.0
- '@types/babel__template': 7.4.4
- '@types/babel__traverse': 7.28.0
-
- '@types/babel__generator@7.27.0':
- dependencies:
- '@babel/types': 7.28.5
-
- '@types/babel__template@7.4.4':
- dependencies:
- '@babel/parser': 7.28.5
- '@babel/types': 7.28.5
-
- '@types/babel__traverse@7.28.0':
- dependencies:
- '@babel/types': 7.28.5
-
- '@types/cacheable-request@6.0.3':
- dependencies:
- '@types/http-cache-semantics': 4.0.4
- '@types/keyv': 3.1.4
- '@types/node': 25.0.3
- '@types/responselike': 1.0.3
-
- '@types/chai@5.2.3':
- dependencies:
- '@types/deep-eql': 4.0.2
- assertion-error: 2.0.1
-
- '@types/debug@4.1.12':
- dependencies:
- '@types/ms': 2.1.0
-
- '@types/deep-eql@4.0.2': {}
-
- '@types/estree-jsx@1.0.5':
- dependencies:
- '@types/estree': 1.0.8
-
- '@types/estree@1.0.8': {}
-
- '@types/fs-extra@9.0.13':
- dependencies:
- '@types/node': 25.0.3
-
- '@types/hast@3.0.4':
- dependencies:
- '@types/unist': 3.0.3
-
- '@types/http-cache-semantics@4.0.4': {}
-
- '@types/json-schema@7.0.15': {}
-
- '@types/keyv@3.1.4':
- dependencies:
- '@types/node': 25.0.3
-
- '@types/mdast@4.0.4':
- dependencies:
- '@types/unist': 3.0.3
-
- '@types/ms@2.1.0': {}
-
- '@types/node@22.19.3':
- dependencies:
- undici-types: 6.21.0
-
- '@types/node@25.0.3':
- dependencies:
- undici-types: 7.16.0
-
- '@types/plist@3.0.5':
- dependencies:
- '@types/node': 25.0.3
- xmlbuilder: 15.1.1
- optional: true
-
- '@types/react-dom@19.2.3(@types/react@19.2.7)':
- dependencies:
- '@types/react': 19.2.7
-
- '@types/react@19.2.7':
- dependencies:
- csstype: 3.2.3
-
- '@types/responselike@1.0.3':
- dependencies:
- '@types/node': 25.0.3
-
- '@types/unist@2.0.11': {}
-
- '@types/unist@3.0.3': {}
-
- '@types/uuid@10.0.0': {}
-
- '@types/verror@1.10.11':
- optional: true
-
- '@types/yauzl@2.10.3':
- dependencies:
- '@types/node': 25.0.3
- optional: true
-
- '@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@eslint-community/regexpp': 4.12.2
- '@typescript-eslint/parser': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/scope-manager': 8.50.0
- '@typescript-eslint/type-utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/visitor-keys': 8.50.0
- eslint: 9.39.2(jiti@2.6.1)
- ignore: 7.0.5
- natural-compare: 1.4.0
- ts-api-utils: 2.1.0(typescript@5.9.3)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/scope-manager': 8.50.0
- '@typescript-eslint/types': 8.50.0
- '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3)
- '@typescript-eslint/visitor-keys': 8.50.0
- debug: 4.4.3
- eslint: 9.39.2(jiti@2.6.1)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/project-service@8.50.0(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3)
- '@typescript-eslint/types': 8.50.0
- debug: 4.4.3
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/scope-manager@8.50.0':
- dependencies:
- '@typescript-eslint/types': 8.50.0
- '@typescript-eslint/visitor-keys': 8.50.0
-
- '@typescript-eslint/tsconfig-utils@8.50.0(typescript@5.9.3)':
- dependencies:
- typescript: 5.9.3
-
- '@typescript-eslint/type-utils@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/types': 8.50.0
- '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3)
- '@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- debug: 4.4.3
- eslint: 9.39.2(jiti@2.6.1)
- ts-api-utils: 2.1.0(typescript@5.9.3)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/types@8.50.0': {}
-
- '@typescript-eslint/typescript-estree@8.50.0(typescript@5.9.3)':
- dependencies:
- '@typescript-eslint/project-service': 8.50.0(typescript@5.9.3)
- '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3)
- '@typescript-eslint/types': 8.50.0
- '@typescript-eslint/visitor-keys': 8.50.0
- debug: 4.4.3
- minimatch: 9.0.5
- semver: 7.7.3
- tinyglobby: 0.2.15
- ts-api-utils: 2.1.0(typescript@5.9.3)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/utils@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
- dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1))
- '@typescript-eslint/scope-manager': 8.50.0
- '@typescript-eslint/types': 8.50.0
- '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3)
- eslint: 9.39.2(jiti@2.6.1)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/visitor-keys@8.50.0':
- dependencies:
- '@typescript-eslint/types': 8.50.0
- eslint-visitor-keys: 4.2.1
-
- '@ungap/structured-clone@1.3.0': {}
-
- '@vitejs/plugin-react@5.1.2(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))':
- dependencies:
- '@babel/core': 7.28.5
- '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5)
- '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5)
- '@rolldown/pluginutils': 1.0.0-beta.53
- '@types/babel__core': 7.20.5
- react-refresh: 0.18.0
- vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)
- transitivePeerDependencies:
- - supports-color
-
- '@vitest/expect@4.0.16':
- dependencies:
- '@standard-schema/spec': 1.1.0
- '@types/chai': 5.2.3
- '@vitest/spy': 4.0.16
- '@vitest/utils': 4.0.16
- chai: 6.2.1
- tinyrainbow: 3.0.3
-
- '@vitest/mocker@4.0.16(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))':
- dependencies:
- '@vitest/spy': 4.0.16
- estree-walker: 3.0.3
- magic-string: 0.30.21
- optionalDependencies:
- vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)
-
- '@vitest/pretty-format@4.0.16':
- dependencies:
- tinyrainbow: 3.0.3
-
- '@vitest/runner@4.0.16':
- dependencies:
- '@vitest/utils': 4.0.16
- pathe: 2.0.3
-
- '@vitest/snapshot@4.0.16':
- dependencies:
- '@vitest/pretty-format': 4.0.16
- magic-string: 0.30.21
- pathe: 2.0.3
-
- '@vitest/spy@4.0.16': {}
-
- '@vitest/utils@4.0.16':
- dependencies:
- '@vitest/pretty-format': 4.0.16
- tinyrainbow: 3.0.3
-
- '@xmldom/xmldom@0.8.11': {}
-
- '@xterm/addon-fit@0.10.0(@xterm/xterm@5.5.0)':
- dependencies:
- '@xterm/xterm': 5.5.0
-
- '@xterm/addon-serialize@0.13.0(@xterm/xterm@5.5.0)':
- dependencies:
- '@xterm/xterm': 5.5.0
-
- '@xterm/addon-web-links@0.11.0(@xterm/xterm@5.5.0)':
- dependencies:
- '@xterm/xterm': 5.5.0
-
- '@xterm/addon-webgl@0.18.0(@xterm/xterm@5.5.0)':
- dependencies:
- '@xterm/xterm': 5.5.0
-
- '@xterm/xterm@5.5.0': {}
-
- abbrev@1.1.1: {}
-
- acorn-jsx@5.3.2(acorn@8.15.0):
- dependencies:
- acorn: 8.15.0
-
- acorn@8.15.0: {}
-
- agent-base@6.0.2:
- dependencies:
- debug: 4.4.3
- transitivePeerDependencies:
- - supports-color
-
- agent-base@7.1.4: {}
-
- agentkeepalive@4.6.0:
- dependencies:
- humanize-ms: 1.2.1
-
- aggregate-error@3.1.0:
- dependencies:
- clean-stack: 2.2.0
- indent-string: 4.0.0
-
- ajv-keywords@3.5.2(ajv@6.12.6):
- dependencies:
- ajv: 6.12.6
-
- ajv@6.12.6:
- dependencies:
- fast-deep-equal: 3.1.3
- fast-json-stable-stringify: 2.1.0
- json-schema-traverse: 0.4.1
- uri-js: 4.4.1
-
- ansi-escapes@7.2.0:
- dependencies:
- environment: 1.1.0
-
- ansi-regex@5.0.1: {}
-
- ansi-regex@6.2.2: {}
-
- ansi-styles@4.3.0:
- dependencies:
- color-convert: 2.0.1
-
- ansi-styles@5.2.0: {}
-
- ansi-styles@6.2.3: {}
-
- app-builder-bin@5.0.0-alpha.12: {}
-
- app-builder-lib@26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12):
- dependencies:
- '@develar/schema-utils': 2.6.5
- '@electron/asar': 3.2.18
- '@electron/fuses': 1.8.0
- '@electron/notarize': 2.5.0
- '@electron/osx-sign': 1.3.1
- '@electron/rebuild': 3.7.0
- '@electron/universal': 2.0.1
- '@malept/flatpak-bundler': 0.4.0
- '@types/fs-extra': 9.0.13
- async-exit-hook: 2.0.1
- builder-util: 26.0.11
- builder-util-runtime: 9.3.1
- chromium-pickle-js: 0.2.0
- config-file-ts: 0.2.8-rc1
- debug: 4.4.3
- dmg-builder: 26.0.12(electron-builder-squirrel-windows@26.0.12)
- dotenv: 16.6.1
- dotenv-expand: 11.0.7
- ejs: 3.1.10
- electron-builder-squirrel-windows: 26.0.12(dmg-builder@26.0.12)
- electron-publish: 26.0.11
- fs-extra: 10.1.0
- hosted-git-info: 4.1.0
- is-ci: 3.0.1
- isbinaryfile: 5.0.7
- js-yaml: 4.1.1
- json5: 2.2.3
- lazy-val: 1.0.5
- minimatch: 10.1.1
- plist: 3.1.0
- resedit: 1.7.2
- semver: 7.7.3
- tar: 6.2.1
- temp-file: 3.4.0
- tiny-async-pool: 1.3.0
- transitivePeerDependencies:
- - bluebird
- - supports-color
-
- argparse@2.0.1: {}
-
- aria-hidden@1.2.6:
- dependencies:
- tslib: 2.8.1
-
- aria-query@5.3.0:
- dependencies:
- dequal: 2.0.3
-
- array-buffer-byte-length@1.0.2:
- dependencies:
- call-bound: 1.0.4
- is-array-buffer: 3.0.5
-
- array-includes@3.1.9:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-abstract: 1.24.1
- es-object-atoms: 1.1.1
- get-intrinsic: 1.3.0
- is-string: 1.1.1
- math-intrinsics: 1.1.0
-
- array.prototype.findlast@1.2.5:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.1
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- es-shim-unscopables: 1.1.0
-
- array.prototype.flat@1.3.3:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.1
- es-shim-unscopables: 1.1.0
-
- array.prototype.flatmap@1.3.3:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.1
- es-shim-unscopables: 1.1.0
-
- array.prototype.tosorted@1.1.4:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.1
- es-errors: 1.3.0
- es-shim-unscopables: 1.1.0
-
- arraybuffer.prototype.slice@1.0.4:
- dependencies:
- array-buffer-byte-length: 1.0.2
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.1
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
- is-array-buffer: 3.0.5
-
- assert-plus@1.0.0:
- optional: true
-
- assertion-error@2.0.1: {}
-
- astral-regex@2.0.0:
- optional: true
-
- async-exit-hook@2.0.1: {}
-
- async-function@1.0.0: {}
-
- async@3.2.6: {}
-
- asynckit@0.4.0: {}
-
- at-least-node@1.0.0: {}
-
- autoprefixer@10.4.23(postcss@8.5.6):
- dependencies:
- browserslist: 4.28.1
- caniuse-lite: 1.0.30001761
- fraction.js: 5.3.4
- picocolors: 1.1.1
- postcss: 8.5.6
- postcss-value-parser: 4.2.0
-
- available-typed-arrays@1.0.7:
- dependencies:
- possible-typed-array-names: 1.1.0
-
- bail@2.0.2: {}
-
- balanced-match@1.0.2: {}
-
- base64-js@1.5.1: {}
-
- baseline-browser-mapping@2.9.10: {}
-
- bl@4.1.0:
- dependencies:
- buffer: 5.7.1
- inherits: 2.0.4
- readable-stream: 3.6.2
-
- boolean@3.2.0:
- optional: true
-
- brace-expansion@1.1.12:
- dependencies:
- balanced-match: 1.0.2
- concat-map: 0.0.1
-
- brace-expansion@2.0.2:
- dependencies:
- balanced-match: 1.0.2
-
- braces@3.0.3:
- dependencies:
- fill-range: 7.1.1
-
- browserslist@4.28.1:
- dependencies:
- baseline-browser-mapping: 2.9.10
- caniuse-lite: 1.0.30001761
- electron-to-chromium: 1.5.267
- node-releases: 2.0.27
- update-browserslist-db: 1.2.3(browserslist@4.28.1)
-
- buffer-crc32@0.2.13: {}
-
- buffer-from@1.1.2: {}
-
- buffer@5.7.1:
- dependencies:
- base64-js: 1.5.1
- ieee754: 1.2.1
-
- builder-util-runtime@9.3.1:
- dependencies:
- debug: 4.4.3
- sax: 1.4.3
- transitivePeerDependencies:
- - supports-color
-
- builder-util@26.0.11:
- dependencies:
- 7zip-bin: 5.2.0
- '@types/debug': 4.1.12
- app-builder-bin: 5.0.0-alpha.12
- builder-util-runtime: 9.3.1
- chalk: 4.1.2
- cross-spawn: 7.0.6
- debug: 4.4.3
- fs-extra: 10.1.0
- http-proxy-agent: 7.0.2
- https-proxy-agent: 7.0.6
- is-ci: 3.0.1
- js-yaml: 4.1.1
- sanitize-filename: 1.6.3
- source-map-support: 0.5.21
- stat-mode: 1.0.0
- temp-file: 3.4.0
- tiny-async-pool: 1.3.0
- transitivePeerDependencies:
- - supports-color
-
- cac@6.7.14: {}
-
- cacache@16.1.3:
- dependencies:
- '@npmcli/fs': 2.1.2
- '@npmcli/move-file': 2.0.1
- chownr: 2.0.0
- fs-minipass: 2.1.0
- glob: 8.1.0
- infer-owner: 1.0.4
- lru-cache: 7.18.3
- minipass: 3.3.6
- minipass-collect: 1.0.2
- minipass-flush: 1.0.5
- minipass-pipeline: 1.2.4
- mkdirp: 1.0.4
- p-map: 4.0.0
- promise-inflight: 1.0.1
- rimraf: 3.0.2
- ssri: 9.0.1
- tar: 6.2.1
- unique-filename: 2.0.1
- transitivePeerDependencies:
- - bluebird
-
- cacheable-lookup@5.0.4: {}
-
- cacheable-request@7.0.4:
- dependencies:
- clone-response: 1.0.3
- get-stream: 5.2.0
- http-cache-semantics: 4.2.0
- keyv: 4.5.4
- lowercase-keys: 2.0.0
- normalize-url: 6.1.0
- responselike: 2.0.1
-
- call-bind-apply-helpers@1.0.2:
- dependencies:
- es-errors: 1.3.0
- function-bind: 1.1.2
-
- call-bind@1.0.8:
- dependencies:
- call-bind-apply-helpers: 1.0.2
- es-define-property: 1.0.1
- get-intrinsic: 1.3.0
- set-function-length: 1.2.2
-
- call-bound@1.0.4:
- dependencies:
- call-bind-apply-helpers: 1.0.2
- get-intrinsic: 1.3.0
-
- callsites@3.1.0: {}
-
- caniuse-lite@1.0.30001761: {}
-
- ccount@2.0.1: {}
-
- chai@6.2.1: {}
-
- chalk@4.1.2:
- dependencies:
- ansi-styles: 4.3.0
- supports-color: 7.2.0
-
- character-entities-html4@2.1.0: {}
-
- character-entities-legacy@3.0.0: {}
-
- character-entities@2.0.2: {}
-
- character-reference-invalid@2.0.1: {}
-
- chokidar@5.0.0:
- dependencies:
- readdirp: 5.0.0
-
- chownr@2.0.0: {}
-
- chromium-pickle-js@0.2.0: {}
-
- ci-info@3.9.0: {}
-
- class-variance-authority@0.7.1:
- dependencies:
- clsx: 2.1.1
-
- clean-stack@2.2.0: {}
-
- cli-cursor@3.1.0:
- dependencies:
- restore-cursor: 3.1.0
-
- cli-cursor@5.0.0:
- dependencies:
- restore-cursor: 5.1.0
-
- cli-spinners@2.9.2: {}
-
- cli-truncate@2.1.0:
- dependencies:
- slice-ansi: 3.0.0
- string-width: 4.2.3
- optional: true
-
- cli-truncate@5.1.1:
- dependencies:
- slice-ansi: 7.1.2
- string-width: 8.1.0
-
- cliui@8.0.1:
- dependencies:
- string-width: 4.2.3
- strip-ansi: 6.0.1
- wrap-ansi: 7.0.0
-
- clone-response@1.0.3:
- dependencies:
- mimic-response: 1.0.1
-
- clone@1.0.4: {}
-
- clsx@2.1.1: {}
-
- color-convert@2.0.1:
- dependencies:
- color-name: 1.1.4
-
- color-name@1.1.4: {}
-
- colorette@2.0.20: {}
-
- combined-stream@1.0.8:
- dependencies:
- delayed-stream: 1.0.0
-
- comma-separated-tokens@2.0.3: {}
-
- commander@14.0.2: {}
-
- commander@5.1.0: {}
-
- commander@9.5.0:
- optional: true
-
- compare-version@0.1.2: {}
-
- concat-map@0.0.1: {}
-
- config-file-ts@0.2.8-rc1:
- dependencies:
- glob: 10.5.0
- typescript: 5.9.3
-
- convert-source-map@2.0.0: {}
-
- core-util-is@1.0.2:
- optional: true
-
- crc@3.8.0:
- dependencies:
- buffer: 5.7.1
- optional: true
-
- cross-dirname@0.1.0:
- optional: true
-
- cross-spawn@7.0.6:
- dependencies:
- path-key: 3.1.1
- shebang-command: 2.0.0
- which: 2.0.2
-
- cssesc@3.0.0: {}
-
- cssstyle@4.6.0:
- dependencies:
- '@asamuzakjp/css-color': 3.2.0
- rrweb-cssom: 0.8.0
-
- csstype@3.2.3: {}
-
- data-urls@5.0.0:
- dependencies:
- whatwg-mimetype: 4.0.0
- whatwg-url: 14.2.0
-
- data-view-buffer@1.0.2:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-data-view: 1.0.2
-
- data-view-byte-length@1.0.2:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-data-view: 1.0.2
-
- data-view-byte-offset@1.0.1:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-data-view: 1.0.2
-
- debug@4.4.3:
- dependencies:
- ms: 2.1.3
-
- decimal.js@10.6.0: {}
-
- decode-named-character-reference@1.2.0:
- dependencies:
- character-entities: 2.0.2
-
- decompress-response@6.0.0:
- dependencies:
- mimic-response: 3.1.0
-
- deep-is@0.1.4: {}
-
- defaults@1.0.4:
- dependencies:
- clone: 1.0.4
-
- defer-to-connect@2.0.1: {}
-
- define-data-property@1.1.4:
- dependencies:
- es-define-property: 1.0.1
- es-errors: 1.3.0
- gopd: 1.2.0
-
- define-properties@1.2.1:
- dependencies:
- define-data-property: 1.1.4
- has-property-descriptors: 1.0.2
- object-keys: 1.1.1
-
- delayed-stream@1.0.0: {}
-
- dequal@2.0.3: {}
-
- detect-libc@2.1.2: {}
-
- detect-node-es@1.1.0: {}
-
- detect-node@2.1.0:
- optional: true
-
- devlop@1.1.0:
- dependencies:
- dequal: 2.0.3
-
- dir-compare@4.2.0:
- dependencies:
- minimatch: 3.1.2
- p-limit: 3.1.0
-
- dmg-builder@26.0.12(electron-builder-squirrel-windows@26.0.12):
- dependencies:
- app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12)
- builder-util: 26.0.11
- builder-util-runtime: 9.3.1
- fs-extra: 10.1.0
- iconv-lite: 0.6.3
- js-yaml: 4.1.1
- optionalDependencies:
- dmg-license: 1.0.11
- transitivePeerDependencies:
- - bluebird
- - electron-builder-squirrel-windows
- - supports-color
-
- dmg-license@1.0.11:
- dependencies:
- '@types/plist': 3.0.5
- '@types/verror': 1.10.11
- ajv: 6.12.6
- crc: 3.8.0
- iconv-corefoundation: 1.1.7
- plist: 3.1.0
- smart-buffer: 4.2.0
- verror: 1.10.1
- optional: true
-
- doctrine@2.1.0:
- dependencies:
- esutils: 2.0.3
-
- dom-accessibility-api@0.5.16: {}
-
- dotenv-expand@11.0.7:
- dependencies:
- dotenv: 16.6.1
-
- dotenv@16.6.1: {}
-
- dunder-proto@1.0.1:
- dependencies:
- call-bind-apply-helpers: 1.0.2
- es-errors: 1.3.0
- gopd: 1.2.0
-
- eastasianwidth@0.2.0: {}
-
- ejs@3.1.10:
- dependencies:
- jake: 10.9.4
-
- electron-builder-squirrel-windows@26.0.12(dmg-builder@26.0.12):
- dependencies:
- app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12)
- builder-util: 26.0.11
- electron-winstaller: 5.4.0
- transitivePeerDependencies:
- - bluebird
- - dmg-builder
- - supports-color
-
- electron-builder@26.0.12(electron-builder-squirrel-windows@26.0.12):
- dependencies:
- app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12)
- builder-util: 26.0.11
- builder-util-runtime: 9.3.1
- chalk: 4.1.2
- dmg-builder: 26.0.12(electron-builder-squirrel-windows@26.0.12)
- fs-extra: 10.1.0
- is-ci: 3.0.1
- lazy-val: 1.0.5
- simple-update-notifier: 2.0.0
- yargs: 17.7.2
- transitivePeerDependencies:
- - bluebird
- - electron-builder-squirrel-windows
- - supports-color
-
- electron-publish@26.0.11:
- dependencies:
- '@types/fs-extra': 9.0.13
- builder-util: 26.0.11
- builder-util-runtime: 9.3.1
- chalk: 4.1.2
- form-data: 4.0.5
- fs-extra: 10.1.0
- lazy-val: 1.0.5
- mime: 2.6.0
- transitivePeerDependencies:
- - supports-color
-
- electron-to-chromium@1.5.267: {}
-
- electron-updater@6.6.2:
- dependencies:
- builder-util-runtime: 9.3.1
- fs-extra: 10.1.0
- js-yaml: 4.1.1
- lazy-val: 1.0.5
- lodash.escaperegexp: 4.1.2
- lodash.isequal: 4.5.0
- semver: 7.7.3
- tiny-typed-emitter: 2.1.0
- transitivePeerDependencies:
- - supports-color
-
- electron-vite@5.0.0(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)):
- dependencies:
- '@babel/core': 7.28.5
- '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.5)
- cac: 6.7.14
- esbuild: 0.25.12
- magic-string: 0.30.21
- picocolors: 1.1.1
- vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)
- transitivePeerDependencies:
- - supports-color
-
- electron-winstaller@5.4.0:
- dependencies:
- '@electron/asar': 3.4.1
- debug: 4.4.3
- fs-extra: 7.0.1
- lodash: 4.17.21
- temp: 0.9.4
- optionalDependencies:
- '@electron/windows-sign': 1.2.2
- transitivePeerDependencies:
- - supports-color
-
- electron@39.2.7:
- dependencies:
- '@electron/get': 2.0.3
- '@types/node': 22.19.3
- extract-zip: 2.0.1
- transitivePeerDependencies:
- - supports-color
-
- emoji-regex@10.6.0: {}
-
- emoji-regex@8.0.0: {}
-
- emoji-regex@9.2.2: {}
-
- encoding@0.1.13:
- dependencies:
- iconv-lite: 0.6.3
- optional: true
-
- end-of-stream@1.4.5:
- dependencies:
- once: 1.4.0
-
- enhanced-resolve@5.18.4:
- dependencies:
- graceful-fs: 4.2.11
- tapable: 2.3.0
-
- entities@6.0.1: {}
-
- env-paths@2.2.1: {}
-
- environment@1.1.0: {}
-
- err-code@2.0.3: {}
-
- es-abstract@1.24.1:
- dependencies:
- array-buffer-byte-length: 1.0.2
- arraybuffer.prototype.slice: 1.0.4
- available-typed-arrays: 1.0.7
- call-bind: 1.0.8
- call-bound: 1.0.4
- data-view-buffer: 1.0.2
- data-view-byte-length: 1.0.2
- data-view-byte-offset: 1.0.1
- es-define-property: 1.0.1
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- es-set-tostringtag: 2.1.0
- es-to-primitive: 1.3.0
- function.prototype.name: 1.1.8
- get-intrinsic: 1.3.0
- get-proto: 1.0.1
- get-symbol-description: 1.1.0
- globalthis: 1.0.4
- gopd: 1.2.0
- has-property-descriptors: 1.0.2
- has-proto: 1.2.0
- has-symbols: 1.1.0
- hasown: 2.0.2
- internal-slot: 1.1.0
- is-array-buffer: 3.0.5
- is-callable: 1.2.7
- is-data-view: 1.0.2
- is-negative-zero: 2.0.3
- is-regex: 1.2.1
- is-set: 2.0.3
- is-shared-array-buffer: 1.0.4
- is-string: 1.1.1
- is-typed-array: 1.1.15
- is-weakref: 1.1.1
- math-intrinsics: 1.1.0
- object-inspect: 1.13.4
- object-keys: 1.1.1
- object.assign: 4.1.7
- own-keys: 1.0.1
- regexp.prototype.flags: 1.5.4
- safe-array-concat: 1.1.3
- safe-push-apply: 1.0.0
- safe-regex-test: 1.1.0
- set-proto: 1.0.0
- stop-iteration-iterator: 1.1.0
- string.prototype.trim: 1.2.10
- string.prototype.trimend: 1.0.9
- string.prototype.trimstart: 1.0.8
- typed-array-buffer: 1.0.3
- typed-array-byte-length: 1.0.3
- typed-array-byte-offset: 1.0.4
- typed-array-length: 1.0.7
- unbox-primitive: 1.1.0
- which-typed-array: 1.1.19
-
- es-define-property@1.0.1: {}
-
- es-errors@1.3.0: {}
-
- es-iterator-helpers@1.2.2:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-abstract: 1.24.1
- es-errors: 1.3.0
- es-set-tostringtag: 2.1.0
- function-bind: 1.1.2
- get-intrinsic: 1.3.0
- globalthis: 1.0.4
- gopd: 1.2.0
- has-property-descriptors: 1.0.2
- has-proto: 1.2.0
- has-symbols: 1.1.0
- internal-slot: 1.1.0
- iterator.prototype: 1.1.5
- safe-array-concat: 1.1.3
-
- es-module-lexer@1.7.0: {}
-
- es-object-atoms@1.1.1:
- dependencies:
- es-errors: 1.3.0
-
- es-set-tostringtag@2.1.0:
- dependencies:
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
- has-tostringtag: 1.0.2
- hasown: 2.0.2
-
- es-shim-unscopables@1.1.0:
- dependencies:
- hasown: 2.0.2
-
- es-to-primitive@1.3.0:
- dependencies:
- is-callable: 1.2.7
- is-date-object: 1.1.0
- is-symbol: 1.1.1
-
- es6-error@4.1.1:
- optional: true
-
- esbuild@0.25.12:
- optionalDependencies:
- '@esbuild/aix-ppc64': 0.25.12
- '@esbuild/android-arm': 0.25.12
- '@esbuild/android-arm64': 0.25.12
- '@esbuild/android-x64': 0.25.12
- '@esbuild/darwin-arm64': 0.25.12
- '@esbuild/darwin-x64': 0.25.12
- '@esbuild/freebsd-arm64': 0.25.12
- '@esbuild/freebsd-x64': 0.25.12
- '@esbuild/linux-arm': 0.25.12
- '@esbuild/linux-arm64': 0.25.12
- '@esbuild/linux-ia32': 0.25.12
- '@esbuild/linux-loong64': 0.25.12
- '@esbuild/linux-mips64el': 0.25.12
- '@esbuild/linux-ppc64': 0.25.12
- '@esbuild/linux-riscv64': 0.25.12
- '@esbuild/linux-s390x': 0.25.12
- '@esbuild/linux-x64': 0.25.12
- '@esbuild/netbsd-arm64': 0.25.12
- '@esbuild/netbsd-x64': 0.25.12
- '@esbuild/openbsd-arm64': 0.25.12
- '@esbuild/openbsd-x64': 0.25.12
- '@esbuild/openharmony-arm64': 0.25.12
- '@esbuild/sunos-x64': 0.25.12
- '@esbuild/win32-arm64': 0.25.12
- '@esbuild/win32-ia32': 0.25.12
- '@esbuild/win32-x64': 0.25.12
-
- esbuild@0.27.2:
- optionalDependencies:
- '@esbuild/aix-ppc64': 0.27.2
- '@esbuild/android-arm': 0.27.2
- '@esbuild/android-arm64': 0.27.2
- '@esbuild/android-x64': 0.27.2
- '@esbuild/darwin-arm64': 0.27.2
- '@esbuild/darwin-x64': 0.27.2
- '@esbuild/freebsd-arm64': 0.27.2
- '@esbuild/freebsd-x64': 0.27.2
- '@esbuild/linux-arm': 0.27.2
- '@esbuild/linux-arm64': 0.27.2
- '@esbuild/linux-ia32': 0.27.2
- '@esbuild/linux-loong64': 0.27.2
- '@esbuild/linux-mips64el': 0.27.2
- '@esbuild/linux-ppc64': 0.27.2
- '@esbuild/linux-riscv64': 0.27.2
- '@esbuild/linux-s390x': 0.27.2
- '@esbuild/linux-x64': 0.27.2
- '@esbuild/netbsd-arm64': 0.27.2
- '@esbuild/netbsd-x64': 0.27.2
- '@esbuild/openbsd-arm64': 0.27.2
- '@esbuild/openbsd-x64': 0.27.2
- '@esbuild/openharmony-arm64': 0.27.2
- '@esbuild/sunos-x64': 0.27.2
- '@esbuild/win32-arm64': 0.27.2
- '@esbuild/win32-ia32': 0.27.2
- '@esbuild/win32-x64': 0.27.2
-
- escalade@3.2.0: {}
-
- escape-string-regexp@4.0.0: {}
-
- escape-string-regexp@5.0.0: {}
-
- eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@2.6.1)):
- dependencies:
- '@babel/core': 7.28.5
- '@babel/parser': 7.28.5
- eslint: 9.39.2(jiti@2.6.1)
- hermes-parser: 0.25.1
- zod: 4.2.1
- zod-validation-error: 4.0.2(zod@4.2.1)
- transitivePeerDependencies:
- - supports-color
-
- eslint-plugin-react@7.37.5(eslint@9.39.2(jiti@2.6.1)):
- dependencies:
- array-includes: 3.1.9
- array.prototype.findlast: 1.2.5
- array.prototype.flatmap: 1.3.3
- array.prototype.tosorted: 1.1.4
- doctrine: 2.1.0
- es-iterator-helpers: 1.2.2
- eslint: 9.39.2(jiti@2.6.1)
- estraverse: 5.3.0
- hasown: 2.0.2
- jsx-ast-utils: 3.3.5
- minimatch: 3.1.2
- object.entries: 1.1.9
- object.fromentries: 2.0.8
- object.values: 1.2.1
- prop-types: 15.8.1
- resolve: 2.0.0-next.5
- semver: 6.3.1
- string.prototype.matchall: 4.0.12
- string.prototype.repeat: 1.0.0
-
- eslint-scope@8.4.0:
- dependencies:
- esrecurse: 4.3.0
- estraverse: 5.3.0
-
- eslint-visitor-keys@3.4.3: {}
-
- eslint-visitor-keys@4.2.1: {}
-
- eslint@9.39.2(jiti@2.6.1):
- dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1))
- '@eslint-community/regexpp': 4.12.2
- '@eslint/config-array': 0.21.1
- '@eslint/config-helpers': 0.4.2
- '@eslint/core': 0.17.0
- '@eslint/eslintrc': 3.3.3
- '@eslint/js': 9.39.2
- '@eslint/plugin-kit': 0.4.1
- '@humanfs/node': 0.16.7
- '@humanwhocodes/module-importer': 1.0.1
- '@humanwhocodes/retry': 0.4.3
- '@types/estree': 1.0.8
- ajv: 6.12.6
- chalk: 4.1.2
- cross-spawn: 7.0.6
- debug: 4.4.3
- escape-string-regexp: 4.0.0
- eslint-scope: 8.4.0
- eslint-visitor-keys: 4.2.1
- espree: 10.4.0
- esquery: 1.6.0
- esutils: 2.0.3
- fast-deep-equal: 3.1.3
- file-entry-cache: 8.0.0
- find-up: 5.0.0
- glob-parent: 6.0.2
- ignore: 5.3.2
- imurmurhash: 0.1.4
- is-glob: 4.0.3
- json-stable-stringify-without-jsonify: 1.0.1
- lodash.merge: 4.6.2
- minimatch: 3.1.2
- natural-compare: 1.4.0
- optionator: 0.9.4
- optionalDependencies:
- jiti: 2.6.1
- transitivePeerDependencies:
- - supports-color
-
- espree@10.4.0:
- dependencies:
- acorn: 8.15.0
- acorn-jsx: 5.3.2(acorn@8.15.0)
- eslint-visitor-keys: 4.2.1
-
- esquery@1.6.0:
- dependencies:
- estraverse: 5.3.0
-
- esrecurse@4.3.0:
- dependencies:
- estraverse: 5.3.0
-
- estraverse@5.3.0: {}
-
- estree-util-is-identifier-name@3.0.0: {}
-
- estree-walker@3.0.3:
- dependencies:
- '@types/estree': 1.0.8
-
- esutils@2.0.3: {}
-
- eventemitter3@5.0.1: {}
-
- expect-type@1.3.0: {}
-
- exponential-backoff@3.1.3: {}
-
- extend@3.0.2: {}
-
- extract-zip@2.0.1:
- dependencies:
- debug: 4.4.3
- get-stream: 5.2.0
- yauzl: 2.10.0
- optionalDependencies:
- '@types/yauzl': 2.10.3
- transitivePeerDependencies:
- - supports-color
-
- extsprintf@1.4.1:
- optional: true
-
- fast-deep-equal@3.1.3: {}
-
- fast-json-stable-stringify@2.1.0: {}
-
- fast-levenshtein@2.0.6: {}
-
- fd-slicer@1.1.0:
- dependencies:
- pend: 1.2.0
-
- fdir@6.5.0(picomatch@4.0.3):
- optionalDependencies:
- picomatch: 4.0.3
-
- file-entry-cache@8.0.0:
- dependencies:
- flat-cache: 4.0.1
-
- filelist@1.0.4:
- dependencies:
- minimatch: 5.1.6
-
- fill-range@7.1.1:
- dependencies:
- to-regex-range: 5.0.1
-
- find-up@5.0.0:
- dependencies:
- locate-path: 6.0.0
- path-exists: 4.0.0
-
- flat-cache@4.0.1:
- dependencies:
- flatted: 3.3.3
- keyv: 4.5.4
-
- flatted@3.3.3: {}
-
- for-each@0.3.5:
- dependencies:
- is-callable: 1.2.7
-
- foreground-child@3.3.1:
- dependencies:
- cross-spawn: 7.0.6
- signal-exit: 4.1.0
-
- form-data@4.0.5:
- dependencies:
- asynckit: 0.4.0
- combined-stream: 1.0.8
- es-set-tostringtag: 2.1.0
- hasown: 2.0.2
- mime-types: 2.1.35
-
- fraction.js@5.3.4: {}
-
- framer-motion@12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
- dependencies:
- motion-dom: 12.23.23
- motion-utils: 12.23.6
- tslib: 2.8.1
- optionalDependencies:
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
-
- fs-extra@10.1.0:
- dependencies:
- graceful-fs: 4.2.11
- jsonfile: 6.2.0
- universalify: 2.0.1
-
- fs-extra@11.3.3:
- dependencies:
- graceful-fs: 4.2.11
- jsonfile: 6.2.0
- universalify: 2.0.1
-
- fs-extra@7.0.1:
- dependencies:
- graceful-fs: 4.2.11
- jsonfile: 4.0.0
- universalify: 0.1.2
-
- fs-extra@8.1.0:
- dependencies:
- graceful-fs: 4.2.11
- jsonfile: 4.0.0
- universalify: 0.1.2
-
- fs-extra@9.1.0:
- dependencies:
- at-least-node: 1.0.0
- graceful-fs: 4.2.11
- jsonfile: 6.2.0
- universalify: 2.0.1
-
- fs-minipass@2.1.0:
- dependencies:
- minipass: 3.3.6
-
- fs.realpath@1.0.0: {}
-
- fsevents@2.3.2:
- optional: true
-
- fsevents@2.3.3:
- optional: true
-
- function-bind@1.1.2: {}
-
- function.prototype.name@1.1.8:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- functions-have-names: 1.2.3
- hasown: 2.0.2
- is-callable: 1.2.7
-
- functions-have-names@1.2.3: {}
-
- generator-function@2.0.1: {}
-
- gensync@1.0.0-beta.2: {}
-
- get-caller-file@2.0.5: {}
-
- get-east-asian-width@1.4.0: {}
-
- get-intrinsic@1.3.0:
- dependencies:
- call-bind-apply-helpers: 1.0.2
- es-define-property: 1.0.1
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- function-bind: 1.1.2
- get-proto: 1.0.1
- gopd: 1.2.0
- has-symbols: 1.1.0
- hasown: 2.0.2
- math-intrinsics: 1.1.0
-
- get-nonce@1.0.1: {}
-
- get-proto@1.0.1:
- dependencies:
- dunder-proto: 1.0.1
- es-object-atoms: 1.1.1
-
- get-stream@5.2.0:
- dependencies:
- pump: 3.0.3
-
- get-symbol-description@1.1.0:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
-
- glob-parent@6.0.2:
- dependencies:
- is-glob: 4.0.3
-
- glob@10.5.0:
- dependencies:
- foreground-child: 3.3.1
- jackspeak: 3.4.3
- minimatch: 9.0.5
- minipass: 7.1.2
- package-json-from-dist: 1.0.1
- path-scurry: 1.11.1
-
- glob@7.2.3:
- dependencies:
- fs.realpath: 1.0.0
- inflight: 1.0.6
- inherits: 2.0.4
- minimatch: 3.1.2
- once: 1.4.0
- path-is-absolute: 1.0.1
-
- glob@8.1.0:
- dependencies:
- fs.realpath: 1.0.0
- inflight: 1.0.6
- inherits: 2.0.4
- minimatch: 5.1.6
- once: 1.4.0
-
- global-agent@3.0.0:
- dependencies:
- boolean: 3.2.0
- es6-error: 4.1.1
- matcher: 3.0.0
- roarr: 2.15.4
- semver: 7.7.3
- serialize-error: 7.0.1
- optional: true
-
- globals@14.0.0: {}
-
- globals@16.5.0: {}
-
- globalthis@1.0.4:
- dependencies:
- define-properties: 1.2.1
- gopd: 1.2.0
-
- gopd@1.2.0: {}
-
- got@11.8.6:
- dependencies:
- '@sindresorhus/is': 4.6.0
- '@szmarczak/http-timer': 4.0.6
- '@types/cacheable-request': 6.0.3
- '@types/responselike': 1.0.3
- cacheable-lookup: 5.0.4
- cacheable-request: 7.0.4
- decompress-response: 6.0.0
- http2-wrapper: 1.0.3
- lowercase-keys: 2.0.0
- p-cancelable: 2.1.1
- responselike: 2.0.1
-
- graceful-fs@4.2.11: {}
-
- has-bigints@1.1.0: {}
-
- has-flag@4.0.0: {}
-
- has-property-descriptors@1.0.2:
- dependencies:
- es-define-property: 1.0.1
-
- has-proto@1.2.0:
- dependencies:
- dunder-proto: 1.0.1
-
- has-symbols@1.1.0: {}
-
- has-tostringtag@1.0.2:
- dependencies:
- has-symbols: 1.1.0
-
- hasown@2.0.2:
- dependencies:
- function-bind: 1.1.2
-
- hast-util-to-jsx-runtime@2.3.6:
- dependencies:
- '@types/estree': 1.0.8
- '@types/hast': 3.0.4
- '@types/unist': 3.0.3
- comma-separated-tokens: 2.0.3
- devlop: 1.1.0
- estree-util-is-identifier-name: 3.0.0
- hast-util-whitespace: 3.0.0
- mdast-util-mdx-expression: 2.0.1
- mdast-util-mdx-jsx: 3.2.0
- mdast-util-mdxjs-esm: 2.0.1
- property-information: 7.1.0
- space-separated-tokens: 2.0.2
- style-to-js: 1.1.21
- unist-util-position: 5.0.0
- vfile-message: 4.0.3
- transitivePeerDependencies:
- - supports-color
-
- hast-util-whitespace@3.0.0:
- dependencies:
- '@types/hast': 3.0.4
-
- hermes-estree@0.25.1: {}
-
- hermes-parser@0.25.1:
- dependencies:
- hermes-estree: 0.25.1
-
- hosted-git-info@4.1.0:
- dependencies:
- lru-cache: 6.0.0
-
- html-encoding-sniffer@4.0.0:
- dependencies:
- whatwg-encoding: 3.1.1
-
- html-url-attributes@3.0.1: {}
-
- http-cache-semantics@4.2.0: {}
-
- http-proxy-agent@5.0.0:
- dependencies:
- '@tootallnate/once': 2.0.0
- agent-base: 6.0.2
- debug: 4.4.3
- transitivePeerDependencies:
- - supports-color
-
- http-proxy-agent@7.0.2:
- dependencies:
- agent-base: 7.1.4
- debug: 4.4.3
- transitivePeerDependencies:
- - supports-color
-
- http2-wrapper@1.0.3:
- dependencies:
- quick-lru: 5.1.1
- resolve-alpn: 1.2.1
-
- https-proxy-agent@5.0.1:
- dependencies:
- agent-base: 6.0.2
- debug: 4.4.3
- transitivePeerDependencies:
- - supports-color
-
- https-proxy-agent@7.0.6:
- dependencies:
- agent-base: 7.1.4
- debug: 4.4.3
- transitivePeerDependencies:
- - supports-color
-
- humanize-ms@1.2.1:
- dependencies:
- ms: 2.1.3
-
- husky@9.1.7: {}
-
- iconv-corefoundation@1.1.7:
- dependencies:
- cli-truncate: 2.1.0
- node-addon-api: 1.7.2
- optional: true
-
- iconv-lite@0.6.3:
- dependencies:
- safer-buffer: 2.1.2
-
- ieee754@1.2.1: {}
-
- ignore@5.3.2: {}
-
- ignore@7.0.5: {}
-
- import-fresh@3.3.1:
- dependencies:
- parent-module: 1.0.1
- resolve-from: 4.0.0
-
- imurmurhash@0.1.4: {}
-
- indent-string@4.0.0: {}
-
- infer-owner@1.0.4: {}
-
- inflight@1.0.6:
- dependencies:
- once: 1.4.0
- wrappy: 1.0.2
-
- inherits@2.0.4: {}
-
- inline-style-parser@0.2.7: {}
-
- internal-slot@1.1.0:
- dependencies:
- es-errors: 1.3.0
- hasown: 2.0.2
- side-channel: 1.1.0
-
- ip-address@10.1.0: {}
-
- is-alphabetical@2.0.1: {}
-
- is-alphanumerical@2.0.1:
- dependencies:
- is-alphabetical: 2.0.1
- is-decimal: 2.0.1
-
- is-array-buffer@3.0.5:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- get-intrinsic: 1.3.0
-
- is-async-function@2.1.1:
- dependencies:
- async-function: 1.0.0
- call-bound: 1.0.4
- get-proto: 1.0.1
- has-tostringtag: 1.0.2
- safe-regex-test: 1.1.0
-
- is-bigint@1.1.0:
- dependencies:
- has-bigints: 1.1.0
-
- is-boolean-object@1.2.2:
- dependencies:
- call-bound: 1.0.4
- has-tostringtag: 1.0.2
-
- is-callable@1.2.7: {}
-
- is-ci@3.0.1:
- dependencies:
- ci-info: 3.9.0
-
- is-core-module@2.16.1:
- dependencies:
- hasown: 2.0.2
-
- is-data-view@1.0.2:
- dependencies:
- call-bound: 1.0.4
- get-intrinsic: 1.3.0
- is-typed-array: 1.1.15
-
- is-date-object@1.1.0:
- dependencies:
- call-bound: 1.0.4
- has-tostringtag: 1.0.2
-
- is-decimal@2.0.1: {}
-
- is-extglob@2.1.1: {}
-
- is-finalizationregistry@1.1.1:
- dependencies:
- call-bound: 1.0.4
-
- is-fullwidth-code-point@3.0.0: {}
-
- is-fullwidth-code-point@5.1.0:
- dependencies:
- get-east-asian-width: 1.4.0
-
- is-generator-function@1.1.2:
- dependencies:
- call-bound: 1.0.4
- generator-function: 2.0.1
- get-proto: 1.0.1
- has-tostringtag: 1.0.2
- safe-regex-test: 1.1.0
-
- is-glob@4.0.3:
- dependencies:
- is-extglob: 2.1.1
-
- is-hexadecimal@2.0.1: {}
-
- is-interactive@1.0.0: {}
-
- is-lambda@1.0.1: {}
-
- is-map@2.0.3: {}
-
- is-negative-zero@2.0.3: {}
-
- is-number-object@1.1.1:
- dependencies:
- call-bound: 1.0.4
- has-tostringtag: 1.0.2
-
- is-number@7.0.0: {}
-
- is-plain-obj@4.1.0: {}
-
- is-potential-custom-element-name@1.0.1: {}
-
- is-regex@1.2.1:
- dependencies:
- call-bound: 1.0.4
- gopd: 1.2.0
- has-tostringtag: 1.0.2
- hasown: 2.0.2
-
- is-set@2.0.3: {}
-
- is-shared-array-buffer@1.0.4:
- dependencies:
- call-bound: 1.0.4
-
- is-string@1.1.1:
- dependencies:
- call-bound: 1.0.4
- has-tostringtag: 1.0.2
-
- is-symbol@1.1.1:
- dependencies:
- call-bound: 1.0.4
- has-symbols: 1.1.0
- safe-regex-test: 1.1.0
-
- is-typed-array@1.1.15:
- dependencies:
- which-typed-array: 1.1.19
-
- is-unicode-supported@0.1.0: {}
-
- is-weakmap@2.0.2: {}
-
- is-weakref@1.1.1:
- dependencies:
- call-bound: 1.0.4
-
- is-weakset@2.0.4:
- dependencies:
- call-bound: 1.0.4
- get-intrinsic: 1.3.0
-
- isarray@2.0.5: {}
-
- isbinaryfile@4.0.10: {}
-
- isbinaryfile@5.0.7: {}
-
- isexe@2.0.0: {}
-
- iterator.prototype@1.1.5:
- dependencies:
- define-data-property: 1.1.4
- es-object-atoms: 1.1.1
- get-intrinsic: 1.3.0
- get-proto: 1.0.1
- has-symbols: 1.1.0
- set-function-name: 2.0.2
-
- jackspeak@3.4.3:
- dependencies:
- '@isaacs/cliui': 8.0.2
- optionalDependencies:
- '@pkgjs/parseargs': 0.11.0
-
- jake@10.9.4:
- dependencies:
- async: 3.2.6
- filelist: 1.0.4
- picocolors: 1.1.1
-
- jiti@2.6.1: {}
-
- js-tokens@4.0.0: {}
-
- js-yaml@4.1.1:
- dependencies:
- argparse: 2.0.1
-
- jsdom@26.1.0:
- dependencies:
- cssstyle: 4.6.0
- data-urls: 5.0.0
- decimal.js: 10.6.0
- html-encoding-sniffer: 4.0.0
- http-proxy-agent: 7.0.2
- https-proxy-agent: 7.0.6
- is-potential-custom-element-name: 1.0.1
- nwsapi: 2.2.23
- parse5: 7.3.0
- rrweb-cssom: 0.8.0
- saxes: 6.0.0
- symbol-tree: 3.2.4
- tough-cookie: 5.1.2
- w3c-xmlserializer: 5.0.0
- webidl-conversions: 7.0.0
- whatwg-encoding: 3.1.1
- whatwg-mimetype: 4.0.0
- whatwg-url: 14.2.0
- ws: 8.18.3
- xml-name-validator: 5.0.0
- transitivePeerDependencies:
- - bufferutil
- - supports-color
- - utf-8-validate
-
- jsesc@3.1.0: {}
-
- json-buffer@3.0.1: {}
-
- json-schema-traverse@0.4.1: {}
-
- json-stable-stringify-without-jsonify@1.0.1: {}
-
- json-stringify-safe@5.0.1:
- optional: true
-
- json5@2.2.3: {}
-
- jsonfile@4.0.0:
- optionalDependencies:
- graceful-fs: 4.2.11
-
- jsonfile@6.2.0:
- dependencies:
- universalify: 2.0.1
- optionalDependencies:
- graceful-fs: 4.2.11
-
- jsx-ast-utils@3.3.5:
- dependencies:
- array-includes: 3.1.9
- array.prototype.flat: 1.3.3
- object.assign: 4.1.7
- object.values: 1.2.1
-
- keyv@4.5.4:
- dependencies:
- json-buffer: 3.0.1
-
- lazy-val@1.0.5: {}
-
- levn@0.4.1:
- dependencies:
- prelude-ls: 1.2.1
- type-check: 0.4.0
-
- lightningcss-android-arm64@1.30.2:
- optional: true
-
- lightningcss-darwin-arm64@1.30.2:
- optional: true
-
- lightningcss-darwin-x64@1.30.2:
- optional: true
-
- lightningcss-freebsd-x64@1.30.2:
- optional: true
-
- lightningcss-linux-arm-gnueabihf@1.30.2:
- optional: true
-
- lightningcss-linux-arm64-gnu@1.30.2:
- optional: true
-
- lightningcss-linux-arm64-musl@1.30.2:
- optional: true
-
- lightningcss-linux-x64-gnu@1.30.2:
- optional: true
-
- lightningcss-linux-x64-musl@1.30.2:
- optional: true
-
- lightningcss-win32-arm64-msvc@1.30.2:
- optional: true
-
- lightningcss-win32-x64-msvc@1.30.2:
- optional: true
-
- lightningcss@1.30.2:
- dependencies:
- detect-libc: 2.1.2
- optionalDependencies:
- lightningcss-android-arm64: 1.30.2
- lightningcss-darwin-arm64: 1.30.2
- lightningcss-darwin-x64: 1.30.2
- lightningcss-freebsd-x64: 1.30.2
- lightningcss-linux-arm-gnueabihf: 1.30.2
- lightningcss-linux-arm64-gnu: 1.30.2
- lightningcss-linux-arm64-musl: 1.30.2
- lightningcss-linux-x64-gnu: 1.30.2
- lightningcss-linux-x64-musl: 1.30.2
- lightningcss-win32-arm64-msvc: 1.30.2
- lightningcss-win32-x64-msvc: 1.30.2
-
- lint-staged@16.2.7:
- dependencies:
- commander: 14.0.2
- listr2: 9.0.5
- micromatch: 4.0.8
- nano-spawn: 2.0.0
- pidtree: 0.6.0
- string-argv: 0.3.2
- yaml: 2.8.2
-
- listr2@9.0.5:
- dependencies:
- cli-truncate: 5.1.1
- colorette: 2.0.20
- eventemitter3: 5.0.1
- log-update: 6.1.0
- rfdc: 1.4.1
- wrap-ansi: 9.0.2
-
- locate-path@6.0.0:
- dependencies:
- p-locate: 5.0.0
-
- lodash.escaperegexp@4.1.2: {}
-
- lodash.isequal@4.5.0: {}
-
- lodash.merge@4.6.2: {}
-
- lodash@4.17.21: {}
-
- log-symbols@4.1.0:
- dependencies:
- chalk: 4.1.2
- is-unicode-supported: 0.1.0
-
- log-update@6.1.0:
- dependencies:
- ansi-escapes: 7.2.0
- cli-cursor: 5.0.0
- slice-ansi: 7.1.2
- strip-ansi: 7.1.2
- wrap-ansi: 9.0.2
-
- longest-streak@3.1.0: {}
-
- loose-envify@1.4.0:
- dependencies:
- js-tokens: 4.0.0
-
- lowercase-keys@2.0.0: {}
-
- lru-cache@10.4.3: {}
-
- lru-cache@5.1.1:
- dependencies:
- yallist: 3.1.1
-
- lru-cache@6.0.0:
- dependencies:
- yallist: 4.0.0
-
- lru-cache@7.18.3: {}
-
- lucide-react@0.560.0(react@19.2.3):
- dependencies:
- react: 19.2.3
-
- lz-string@1.5.0: {}
-
- magic-string@0.30.21:
- dependencies:
- '@jridgewell/sourcemap-codec': 1.5.5
-
- make-fetch-happen@10.2.1:
- dependencies:
- agentkeepalive: 4.6.0
- cacache: 16.1.3
- http-cache-semantics: 4.2.0
- http-proxy-agent: 5.0.0
- https-proxy-agent: 5.0.1
- is-lambda: 1.0.1
- lru-cache: 7.18.3
- minipass: 3.3.6
- minipass-collect: 1.0.2
- minipass-fetch: 2.1.2
- minipass-flush: 1.0.5
- minipass-pipeline: 1.2.4
- negotiator: 0.6.4
- promise-retry: 2.0.1
- socks-proxy-agent: 7.0.0
- ssri: 9.0.1
- transitivePeerDependencies:
- - bluebird
- - supports-color
-
- markdown-table@3.0.4: {}
-
- matcher@3.0.0:
- dependencies:
- escape-string-regexp: 4.0.0
- optional: true
-
- math-intrinsics@1.1.0: {}
-
- mdast-util-find-and-replace@3.0.2:
- dependencies:
- '@types/mdast': 4.0.4
- escape-string-regexp: 5.0.0
- unist-util-is: 6.0.1
- unist-util-visit-parents: 6.0.2
-
- mdast-util-from-markdown@2.0.2:
- dependencies:
- '@types/mdast': 4.0.4
- '@types/unist': 3.0.3
- decode-named-character-reference: 1.2.0
- devlop: 1.1.0
- mdast-util-to-string: 4.0.0
- micromark: 4.0.2
- micromark-util-decode-numeric-character-reference: 2.0.2
- micromark-util-decode-string: 2.0.1
- micromark-util-normalize-identifier: 2.0.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
- unist-util-stringify-position: 4.0.0
- transitivePeerDependencies:
- - supports-color
-
- mdast-util-gfm-autolink-literal@2.0.1:
- dependencies:
- '@types/mdast': 4.0.4
- ccount: 2.0.1
- devlop: 1.1.0
- mdast-util-find-and-replace: 3.0.2
- micromark-util-character: 2.1.1
-
- mdast-util-gfm-footnote@2.1.0:
- dependencies:
- '@types/mdast': 4.0.4
- devlop: 1.1.0
- mdast-util-from-markdown: 2.0.2
- mdast-util-to-markdown: 2.1.2
- micromark-util-normalize-identifier: 2.0.1
- transitivePeerDependencies:
- - supports-color
-
- mdast-util-gfm-strikethrough@2.0.0:
- dependencies:
- '@types/mdast': 4.0.4
- mdast-util-from-markdown: 2.0.2
- mdast-util-to-markdown: 2.1.2
- transitivePeerDependencies:
- - supports-color
-
- mdast-util-gfm-table@2.0.0:
- dependencies:
- '@types/mdast': 4.0.4
- devlop: 1.1.0
- markdown-table: 3.0.4
- mdast-util-from-markdown: 2.0.2
- mdast-util-to-markdown: 2.1.2
- transitivePeerDependencies:
- - supports-color
-
- mdast-util-gfm-task-list-item@2.0.0:
- dependencies:
- '@types/mdast': 4.0.4
- devlop: 1.1.0
- mdast-util-from-markdown: 2.0.2
- mdast-util-to-markdown: 2.1.2
- transitivePeerDependencies:
- - supports-color
-
- mdast-util-gfm@3.1.0:
- dependencies:
- mdast-util-from-markdown: 2.0.2
- mdast-util-gfm-autolink-literal: 2.0.1
- mdast-util-gfm-footnote: 2.1.0
- mdast-util-gfm-strikethrough: 2.0.0
- mdast-util-gfm-table: 2.0.0
- mdast-util-gfm-task-list-item: 2.0.0
- mdast-util-to-markdown: 2.1.2
- transitivePeerDependencies:
- - supports-color
-
- mdast-util-mdx-expression@2.0.1:
- dependencies:
- '@types/estree-jsx': 1.0.5
- '@types/hast': 3.0.4
- '@types/mdast': 4.0.4
- devlop: 1.1.0
- mdast-util-from-markdown: 2.0.2
- mdast-util-to-markdown: 2.1.2
- transitivePeerDependencies:
- - supports-color
-
- mdast-util-mdx-jsx@3.2.0:
- dependencies:
- '@types/estree-jsx': 1.0.5
- '@types/hast': 3.0.4
- '@types/mdast': 4.0.4
- '@types/unist': 3.0.3
- ccount: 2.0.1
- devlop: 1.1.0
- mdast-util-from-markdown: 2.0.2
- mdast-util-to-markdown: 2.1.2
- parse-entities: 4.0.2
- stringify-entities: 4.0.4
- unist-util-stringify-position: 4.0.0
- vfile-message: 4.0.3
- transitivePeerDependencies:
- - supports-color
-
- mdast-util-mdxjs-esm@2.0.1:
- dependencies:
- '@types/estree-jsx': 1.0.5
- '@types/hast': 3.0.4
- '@types/mdast': 4.0.4
- devlop: 1.1.0
- mdast-util-from-markdown: 2.0.2
- mdast-util-to-markdown: 2.1.2
- transitivePeerDependencies:
- - supports-color
-
- mdast-util-phrasing@4.1.0:
- dependencies:
- '@types/mdast': 4.0.4
- unist-util-is: 6.0.1
-
- mdast-util-to-hast@13.2.1:
- dependencies:
- '@types/hast': 3.0.4
- '@types/mdast': 4.0.4
- '@ungap/structured-clone': 1.3.0
- devlop: 1.1.0
- micromark-util-sanitize-uri: 2.0.1
- trim-lines: 3.0.1
- unist-util-position: 5.0.0
- unist-util-visit: 5.0.0
- vfile: 6.0.3
-
- mdast-util-to-markdown@2.1.2:
- dependencies:
- '@types/mdast': 4.0.4
- '@types/unist': 3.0.3
- longest-streak: 3.1.0
- mdast-util-phrasing: 4.1.0
- mdast-util-to-string: 4.0.0
- micromark-util-classify-character: 2.0.1
- micromark-util-decode-string: 2.0.1
- unist-util-visit: 5.0.0
- zwitch: 2.0.4
-
- mdast-util-to-string@4.0.0:
- dependencies:
- '@types/mdast': 4.0.4
-
- micromark-core-commonmark@2.0.3:
- dependencies:
- decode-named-character-reference: 1.2.0
- devlop: 1.1.0
- micromark-factory-destination: 2.0.1
- micromark-factory-label: 2.0.1
- micromark-factory-space: 2.0.1
- micromark-factory-title: 2.0.1
- micromark-factory-whitespace: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-chunked: 2.0.1
- micromark-util-classify-character: 2.0.1
- micromark-util-html-tag-name: 2.0.1
- micromark-util-normalize-identifier: 2.0.1
- micromark-util-resolve-all: 2.0.1
- micromark-util-subtokenize: 2.1.0
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-extension-gfm-autolink-literal@2.1.0:
- dependencies:
- micromark-util-character: 2.1.1
- micromark-util-sanitize-uri: 2.0.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-extension-gfm-footnote@2.1.0:
- dependencies:
- devlop: 1.1.0
- micromark-core-commonmark: 2.0.3
- micromark-factory-space: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-normalize-identifier: 2.0.1
- micromark-util-sanitize-uri: 2.0.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-extension-gfm-strikethrough@2.1.0:
- dependencies:
- devlop: 1.1.0
- micromark-util-chunked: 2.0.1
- micromark-util-classify-character: 2.0.1
- micromark-util-resolve-all: 2.0.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-extension-gfm-table@2.1.1:
- dependencies:
- devlop: 1.1.0
- micromark-factory-space: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-extension-gfm-tagfilter@2.0.0:
- dependencies:
- micromark-util-types: 2.0.2
-
- micromark-extension-gfm-task-list-item@2.1.0:
- dependencies:
- devlop: 1.1.0
- micromark-factory-space: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-extension-gfm@3.0.0:
- dependencies:
- micromark-extension-gfm-autolink-literal: 2.1.0
- micromark-extension-gfm-footnote: 2.1.0
- micromark-extension-gfm-strikethrough: 2.1.0
- micromark-extension-gfm-table: 2.1.1
- micromark-extension-gfm-tagfilter: 2.0.0
- micromark-extension-gfm-task-list-item: 2.1.0
- micromark-util-combine-extensions: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-factory-destination@2.0.1:
- dependencies:
- micromark-util-character: 2.1.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-factory-label@2.0.1:
- dependencies:
- devlop: 1.1.0
- micromark-util-character: 2.1.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-factory-space@2.0.1:
- dependencies:
- micromark-util-character: 2.1.1
- micromark-util-types: 2.0.2
-
- micromark-factory-title@2.0.1:
- dependencies:
- micromark-factory-space: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-factory-whitespace@2.0.1:
- dependencies:
- micromark-factory-space: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-util-character@2.1.1:
- dependencies:
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-util-chunked@2.0.1:
- dependencies:
- micromark-util-symbol: 2.0.1
-
- micromark-util-classify-character@2.0.1:
- dependencies:
- micromark-util-character: 2.1.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-util-combine-extensions@2.0.1:
- dependencies:
- micromark-util-chunked: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-util-decode-numeric-character-reference@2.0.2:
- dependencies:
- micromark-util-symbol: 2.0.1
-
- micromark-util-decode-string@2.0.1:
- dependencies:
- decode-named-character-reference: 1.2.0
- micromark-util-character: 2.1.1
- micromark-util-decode-numeric-character-reference: 2.0.2
- micromark-util-symbol: 2.0.1
-
- micromark-util-encode@2.0.1: {}
-
- micromark-util-html-tag-name@2.0.1: {}
-
- micromark-util-normalize-identifier@2.0.1:
- dependencies:
- micromark-util-symbol: 2.0.1
-
- micromark-util-resolve-all@2.0.1:
- dependencies:
- micromark-util-types: 2.0.2
-
- micromark-util-sanitize-uri@2.0.1:
- dependencies:
- micromark-util-character: 2.1.1
- micromark-util-encode: 2.0.1
- micromark-util-symbol: 2.0.1
-
- micromark-util-subtokenize@2.1.0:
- dependencies:
- devlop: 1.1.0
- micromark-util-chunked: 2.0.1
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
-
- micromark-util-symbol@2.0.1: {}
-
- micromark-util-types@2.0.2: {}
-
- micromark@4.0.2:
- dependencies:
- '@types/debug': 4.1.12
- debug: 4.4.3
- decode-named-character-reference: 1.2.0
- devlop: 1.1.0
- micromark-core-commonmark: 2.0.3
- micromark-factory-space: 2.0.1
- micromark-util-character: 2.1.1
- micromark-util-chunked: 2.0.1
- micromark-util-combine-extensions: 2.0.1
- micromark-util-decode-numeric-character-reference: 2.0.2
- micromark-util-encode: 2.0.1
- micromark-util-normalize-identifier: 2.0.1
- micromark-util-resolve-all: 2.0.1
- micromark-util-sanitize-uri: 2.0.1
- micromark-util-subtokenize: 2.1.0
- micromark-util-symbol: 2.0.1
- micromark-util-types: 2.0.2
- transitivePeerDependencies:
- - supports-color
-
- micromatch@4.0.8:
- dependencies:
- braces: 3.0.3
- picomatch: 2.3.1
-
- mime-db@1.52.0: {}
-
- mime-types@2.1.35:
- dependencies:
- mime-db: 1.52.0
-
- mime@2.6.0: {}
-
- mimic-fn@2.1.0: {}
-
- mimic-function@5.0.1: {}
-
- mimic-response@1.0.1: {}
-
- mimic-response@3.1.0: {}
-
- minimatch@10.1.1:
- dependencies:
- '@isaacs/brace-expansion': 5.0.0
-
- minimatch@3.1.2:
- dependencies:
- brace-expansion: 1.1.12
-
- minimatch@5.1.6:
- dependencies:
- brace-expansion: 2.0.2
-
- minimatch@9.0.5:
- dependencies:
- brace-expansion: 2.0.2
-
- minimist@1.2.8: {}
-
- minipass-collect@1.0.2:
- dependencies:
- minipass: 3.3.6
-
- minipass-fetch@2.1.2:
- dependencies:
- minipass: 3.3.6
- minipass-sized: 1.0.3
- minizlib: 2.1.2
- optionalDependencies:
- encoding: 0.1.13
-
- minipass-flush@1.0.5:
- dependencies:
- minipass: 3.3.6
-
- minipass-pipeline@1.2.4:
- dependencies:
- minipass: 3.3.6
-
- minipass-sized@1.0.3:
- dependencies:
- minipass: 3.3.6
-
- minipass@3.3.6:
- dependencies:
- yallist: 4.0.0
-
- minipass@5.0.0: {}
-
- minipass@7.1.2: {}
-
- minizlib@2.1.2:
- dependencies:
- minipass: 3.3.6
- yallist: 4.0.0
-
- mkdirp@0.5.6:
- dependencies:
- minimist: 1.2.8
-
- mkdirp@1.0.4: {}
-
- motion-dom@12.23.23:
- dependencies:
- motion-utils: 12.23.6
-
- motion-utils@12.23.6: {}
-
- motion@12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
- dependencies:
- framer-motion: 12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- tslib: 2.8.1
- optionalDependencies:
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
-
- ms@2.1.3: {}
-
- nano-spawn@2.0.0: {}
-
- nanoid@3.3.11: {}
-
- natural-compare@1.4.0: {}
-
- negotiator@0.6.4: {}
-
- node-abi@3.85.0:
- dependencies:
- semver: 7.7.3
-
- node-addon-api@1.7.2:
- optional: true
-
- node-api-version@0.2.1:
- dependencies:
- semver: 7.7.3
-
- node-releases@2.0.27: {}
-
- nopt@6.0.0:
- dependencies:
- abbrev: 1.1.1
-
- normalize-url@6.1.0: {}
-
- nwsapi@2.2.23: {}
-
- object-assign@4.1.1: {}
-
- object-inspect@1.13.4: {}
-
- object-keys@1.1.1: {}
-
- object.assign@4.1.7:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
- has-symbols: 1.1.0
- object-keys: 1.1.1
-
- object.entries@1.1.9:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
-
- object.fromentries@2.0.8:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.1
- es-object-atoms: 1.1.1
-
- object.values@1.2.1:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
-
- obug@2.1.1: {}
-
- once@1.4.0:
- dependencies:
- wrappy: 1.0.2
-
- onetime@5.1.2:
- dependencies:
- mimic-fn: 2.1.0
-
- onetime@7.0.0:
- dependencies:
- mimic-function: 5.0.1
-
- optionator@0.9.4:
- dependencies:
- deep-is: 0.1.4
- fast-levenshtein: 2.0.6
- levn: 0.4.1
- prelude-ls: 1.2.1
- type-check: 0.4.0
- word-wrap: 1.2.5
-
- ora@5.4.1:
- dependencies:
- bl: 4.1.0
- chalk: 4.1.2
- cli-cursor: 3.1.0
- cli-spinners: 2.9.2
- is-interactive: 1.0.0
- is-unicode-supported: 0.1.0
- log-symbols: 4.1.0
- strip-ansi: 6.0.1
- wcwidth: 1.0.1
-
- own-keys@1.0.1:
- dependencies:
- get-intrinsic: 1.3.0
- object-keys: 1.1.1
- safe-push-apply: 1.0.0
-
- p-cancelable@2.1.1: {}
-
- p-limit@3.1.0:
- dependencies:
- yocto-queue: 0.1.0
-
- p-locate@5.0.0:
- dependencies:
- p-limit: 3.1.0
-
- p-map@4.0.0:
- dependencies:
- aggregate-error: 3.1.0
-
- package-json-from-dist@1.0.1: {}
-
- parent-module@1.0.1:
- dependencies:
- callsites: 3.1.0
-
- parse-entities@4.0.2:
- dependencies:
- '@types/unist': 2.0.11
- character-entities-legacy: 3.0.0
- character-reference-invalid: 2.0.1
- decode-named-character-reference: 1.2.0
- is-alphanumerical: 2.0.1
- is-decimal: 2.0.1
- is-hexadecimal: 2.0.1
-
- parse5@7.3.0:
- dependencies:
- entities: 6.0.1
-
- path-exists@4.0.0: {}
-
- path-is-absolute@1.0.1: {}
-
- path-key@3.1.1: {}
-
- path-parse@1.0.7: {}
-
- path-scurry@1.11.1:
- dependencies:
- lru-cache: 10.4.3
- minipass: 7.1.2
-
- pathe@2.0.3: {}
-
- pe-library@0.4.1: {}
-
- pend@1.2.0: {}
-
- picocolors@1.1.1: {}
-
- picomatch@2.3.1: {}
-
- picomatch@4.0.3: {}
-
- pidtree@0.6.0: {}
-
- playwright-core@1.57.0: {}
-
- playwright@1.57.0:
- dependencies:
- playwright-core: 1.57.0
- optionalDependencies:
- fsevents: 2.3.2
-
- plist@3.1.0:
- dependencies:
- '@xmldom/xmldom': 0.8.11
- base64-js: 1.5.1
- xmlbuilder: 15.1.1
-
- possible-typed-array-names@1.1.0: {}
-
- postcss-selector-parser@6.0.10:
- dependencies:
- cssesc: 3.0.0
- util-deprecate: 1.0.2
-
- postcss-value-parser@4.2.0: {}
-
- postcss@8.5.6:
- dependencies:
- nanoid: 3.3.11
- picocolors: 1.1.1
- source-map-js: 1.2.1
-
- postject@1.0.0-alpha.6:
- dependencies:
- commander: 9.5.0
- optional: true
-
- prelude-ls@1.2.1: {}
-
- pretty-format@27.5.1:
- dependencies:
- ansi-regex: 5.0.1
- ansi-styles: 5.2.0
- react-is: 17.0.2
-
- proc-log@2.0.1: {}
-
- progress@2.0.3: {}
-
- promise-inflight@1.0.1: {}
-
- promise-retry@2.0.1:
- dependencies:
- err-code: 2.0.3
- retry: 0.12.0
-
- prop-types@15.8.1:
- dependencies:
- loose-envify: 1.4.0
- object-assign: 4.1.1
- react-is: 16.13.1
-
- property-information@7.1.0: {}
-
- pump@3.0.3:
- dependencies:
- end-of-stream: 1.4.5
- once: 1.4.0
-
- punycode@2.3.1: {}
-
- quick-lru@5.1.1: {}
-
- react-dom@19.2.3(react@19.2.3):
- dependencies:
- react: 19.2.3
- scheduler: 0.27.0
-
- react-is@16.13.1: {}
-
- react-is@17.0.2: {}
-
- react-markdown@10.1.0(@types/react@19.2.7)(react@19.2.3):
- dependencies:
- '@types/hast': 3.0.4
- '@types/mdast': 4.0.4
- '@types/react': 19.2.7
- devlop: 1.1.0
- hast-util-to-jsx-runtime: 2.3.6
- html-url-attributes: 3.0.1
- mdast-util-to-hast: 13.2.1
- react: 19.2.3
- remark-parse: 11.0.0
- remark-rehype: 11.1.2
- unified: 11.0.5
- unist-util-visit: 5.0.0
- vfile: 6.0.3
- transitivePeerDependencies:
- - supports-color
-
- react-refresh@0.18.0: {}
-
- react-remove-scroll-bar@2.3.8(@types/react@19.2.7)(react@19.2.3):
- dependencies:
- react: 19.2.3
- react-style-singleton: 2.2.3(@types/react@19.2.7)(react@19.2.3)
- tslib: 2.8.1
- optionalDependencies:
- '@types/react': 19.2.7
-
- react-remove-scroll@2.7.2(@types/react@19.2.7)(react@19.2.3):
- dependencies:
- react: 19.2.3
- react-remove-scroll-bar: 2.3.8(@types/react@19.2.7)(react@19.2.3)
- react-style-singleton: 2.2.3(@types/react@19.2.7)(react@19.2.3)
- tslib: 2.8.1
- use-callback-ref: 1.3.3(@types/react@19.2.7)(react@19.2.3)
- use-sidecar: 1.1.3(@types/react@19.2.7)(react@19.2.3)
- optionalDependencies:
- '@types/react': 19.2.7
-
- react-resizable-panels@3.0.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
- dependencies:
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
-
- react-style-singleton@2.2.3(@types/react@19.2.7)(react@19.2.3):
- dependencies:
- get-nonce: 1.0.1
- react: 19.2.3
- tslib: 2.8.1
- optionalDependencies:
- '@types/react': 19.2.7
-
- react@19.2.3: {}
-
- read-binary-file-arch@1.0.6:
- dependencies:
- debug: 4.4.3
- transitivePeerDependencies:
- - supports-color
-
- readable-stream@3.6.2:
- dependencies:
- inherits: 2.0.4
- string_decoder: 1.3.0
- util-deprecate: 1.0.2
-
- readdirp@5.0.0: {}
-
- reflect.getprototypeof@1.0.10:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.1
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- get-intrinsic: 1.3.0
- get-proto: 1.0.1
- which-builtin-type: 1.2.1
-
- regexp.prototype.flags@1.5.4:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-errors: 1.3.0
- get-proto: 1.0.1
- gopd: 1.2.0
- set-function-name: 2.0.2
-
- remark-gfm@4.0.1:
- dependencies:
- '@types/mdast': 4.0.4
- mdast-util-gfm: 3.1.0
- micromark-extension-gfm: 3.0.0
- remark-parse: 11.0.0
- remark-stringify: 11.0.0
- unified: 11.0.5
- transitivePeerDependencies:
- - supports-color
-
- remark-parse@11.0.0:
- dependencies:
- '@types/mdast': 4.0.4
- mdast-util-from-markdown: 2.0.2
- micromark-util-types: 2.0.2
- unified: 11.0.5
- transitivePeerDependencies:
- - supports-color
-
- remark-rehype@11.1.2:
- dependencies:
- '@types/hast': 3.0.4
- '@types/mdast': 4.0.4
- mdast-util-to-hast: 13.2.1
- unified: 11.0.5
- vfile: 6.0.3
-
- remark-stringify@11.0.0:
- dependencies:
- '@types/mdast': 4.0.4
- mdast-util-to-markdown: 2.1.2
- unified: 11.0.5
-
- require-directory@2.1.1: {}
-
- resedit@1.7.2:
- dependencies:
- pe-library: 0.4.1
-
- resolve-alpn@1.2.1: {}
-
- resolve-from@4.0.0: {}
-
- resolve@2.0.0-next.5:
- dependencies:
- is-core-module: 2.16.1
- path-parse: 1.0.7
- supports-preserve-symlinks-flag: 1.0.0
-
- responselike@2.0.1:
- dependencies:
- lowercase-keys: 2.0.0
-
- restore-cursor@3.1.0:
- dependencies:
- onetime: 5.1.2
- signal-exit: 3.0.7
-
- restore-cursor@5.1.0:
- dependencies:
- onetime: 7.0.0
- signal-exit: 4.1.0
-
- retry@0.12.0: {}
-
- rfdc@1.4.1: {}
-
- rimraf@2.6.3:
- dependencies:
- glob: 7.2.3
-
- rimraf@3.0.2:
- dependencies:
- glob: 7.2.3
-
- roarr@2.15.4:
- dependencies:
- boolean: 3.2.0
- detect-node: 2.1.0
- globalthis: 1.0.4
- json-stringify-safe: 5.0.1
- semver-compare: 1.0.0
- sprintf-js: 1.1.3
- optional: true
-
- rollup@4.53.5:
- dependencies:
- '@types/estree': 1.0.8
- optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.53.5
- '@rollup/rollup-android-arm64': 4.53.5
- '@rollup/rollup-darwin-arm64': 4.53.5
- '@rollup/rollup-darwin-x64': 4.53.5
- '@rollup/rollup-freebsd-arm64': 4.53.5
- '@rollup/rollup-freebsd-x64': 4.53.5
- '@rollup/rollup-linux-arm-gnueabihf': 4.53.5
- '@rollup/rollup-linux-arm-musleabihf': 4.53.5
- '@rollup/rollup-linux-arm64-gnu': 4.53.5
- '@rollup/rollup-linux-arm64-musl': 4.53.5
- '@rollup/rollup-linux-loong64-gnu': 4.53.5
- '@rollup/rollup-linux-ppc64-gnu': 4.53.5
- '@rollup/rollup-linux-riscv64-gnu': 4.53.5
- '@rollup/rollup-linux-riscv64-musl': 4.53.5
- '@rollup/rollup-linux-s390x-gnu': 4.53.5
- '@rollup/rollup-linux-x64-gnu': 4.53.5
- '@rollup/rollup-linux-x64-musl': 4.53.5
- '@rollup/rollup-openharmony-arm64': 4.53.5
- '@rollup/rollup-win32-arm64-msvc': 4.53.5
- '@rollup/rollup-win32-ia32-msvc': 4.53.5
- '@rollup/rollup-win32-x64-gnu': 4.53.5
- '@rollup/rollup-win32-x64-msvc': 4.53.5
- fsevents: 2.3.3
-
- rrweb-cssom@0.8.0: {}
-
- safe-array-concat@1.1.3:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- get-intrinsic: 1.3.0
- has-symbols: 1.1.0
- isarray: 2.0.5
-
- safe-buffer@5.2.1: {}
-
- safe-push-apply@1.0.0:
- dependencies:
- es-errors: 1.3.0
- isarray: 2.0.5
-
- safe-regex-test@1.1.0:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-regex: 1.2.1
-
- safer-buffer@2.1.2: {}
-
- sanitize-filename@1.6.3:
- dependencies:
- truncate-utf8-bytes: 1.0.2
-
- sax@1.4.3: {}
-
- saxes@6.0.0:
- dependencies:
- xmlchars: 2.2.0
-
- scheduler@0.27.0: {}
-
- semver-compare@1.0.0:
- optional: true
-
- semver@5.7.2: {}
-
- semver@6.3.1: {}
-
- semver@7.7.3: {}
-
- serialize-error@7.0.1:
- dependencies:
- type-fest: 0.13.1
- optional: true
-
- set-function-length@1.2.2:
- dependencies:
- define-data-property: 1.1.4
- es-errors: 1.3.0
- function-bind: 1.1.2
- get-intrinsic: 1.3.0
- gopd: 1.2.0
- has-property-descriptors: 1.0.2
-
- set-function-name@2.0.2:
- dependencies:
- define-data-property: 1.1.4
- es-errors: 1.3.0
- functions-have-names: 1.2.3
- has-property-descriptors: 1.0.2
-
- set-proto@1.0.0:
- dependencies:
- dunder-proto: 1.0.1
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
-
- shebang-command@2.0.0:
- dependencies:
- shebang-regex: 3.0.0
-
- shebang-regex@3.0.0: {}
-
- side-channel-list@1.0.0:
- dependencies:
- es-errors: 1.3.0
- object-inspect: 1.13.4
-
- side-channel-map@1.0.1:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
- object-inspect: 1.13.4
-
- side-channel-weakmap@1.0.2:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
- object-inspect: 1.13.4
- side-channel-map: 1.0.1
-
- side-channel@1.1.0:
- dependencies:
- es-errors: 1.3.0
- object-inspect: 1.13.4
- side-channel-list: 1.0.0
- side-channel-map: 1.0.1
- side-channel-weakmap: 1.0.2
-
- siginfo@2.0.0: {}
-
- signal-exit@3.0.7: {}
-
- signal-exit@4.1.0: {}
-
- simple-update-notifier@2.0.0:
- dependencies:
- semver: 7.7.3
-
- slice-ansi@3.0.0:
- dependencies:
- ansi-styles: 4.3.0
- astral-regex: 2.0.0
- is-fullwidth-code-point: 3.0.0
- optional: true
-
- slice-ansi@7.1.2:
- dependencies:
- ansi-styles: 6.2.3
- is-fullwidth-code-point: 5.1.0
-
- smart-buffer@4.2.0: {}
-
- socks-proxy-agent@7.0.0:
- dependencies:
- agent-base: 6.0.2
- debug: 4.4.3
- socks: 2.8.7
- transitivePeerDependencies:
- - supports-color
-
- socks@2.8.7:
- dependencies:
- ip-address: 10.1.0
- smart-buffer: 4.2.0
-
- source-map-js@1.2.1: {}
-
- source-map-support@0.5.21:
- dependencies:
- buffer-from: 1.1.2
- source-map: 0.6.1
-
- source-map@0.6.1: {}
-
- space-separated-tokens@2.0.2: {}
-
- sprintf-js@1.1.3:
- optional: true
-
- ssri@9.0.1:
- dependencies:
- minipass: 3.3.6
-
- stackback@0.0.2: {}
-
- stat-mode@1.0.0: {}
-
- std-env@3.10.0: {}
-
- stop-iteration-iterator@1.1.0:
- dependencies:
- es-errors: 1.3.0
- internal-slot: 1.1.0
-
- string-argv@0.3.2: {}
-
- string-width@4.2.3:
- dependencies:
- emoji-regex: 8.0.0
- is-fullwidth-code-point: 3.0.0
- strip-ansi: 6.0.1
-
- string-width@5.1.2:
- dependencies:
- eastasianwidth: 0.2.0
- emoji-regex: 9.2.2
- strip-ansi: 7.1.2
-
- string-width@7.2.0:
- dependencies:
- emoji-regex: 10.6.0
- get-east-asian-width: 1.4.0
- strip-ansi: 7.1.2
-
- string-width@8.1.0:
- dependencies:
- get-east-asian-width: 1.4.0
- strip-ansi: 7.1.2
-
- string.prototype.matchall@4.0.12:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-abstract: 1.24.1
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- get-intrinsic: 1.3.0
- gopd: 1.2.0
- has-symbols: 1.1.0
- internal-slot: 1.1.0
- regexp.prototype.flags: 1.5.4
- set-function-name: 2.0.2
- side-channel: 1.1.0
-
- string.prototype.repeat@1.0.0:
- dependencies:
- define-properties: 1.2.1
- es-abstract: 1.24.1
-
- string.prototype.trim@1.2.10:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-data-property: 1.1.4
- define-properties: 1.2.1
- es-abstract: 1.24.1
- es-object-atoms: 1.1.1
- has-property-descriptors: 1.0.2
-
- string.prototype.trimend@1.0.9:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
-
- string.prototype.trimstart@1.0.8:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
-
- string_decoder@1.3.0:
- dependencies:
- safe-buffer: 5.2.1
-
- stringify-entities@4.0.4:
- dependencies:
- character-entities-html4: 2.1.0
- character-entities-legacy: 3.0.0
-
- strip-ansi@6.0.1:
- dependencies:
- ansi-regex: 5.0.1
-
- strip-ansi@7.1.2:
- dependencies:
- ansi-regex: 6.2.2
-
- strip-json-comments@3.1.1: {}
-
- style-to-js@1.1.21:
- dependencies:
- style-to-object: 1.0.14
-
- style-to-object@1.0.14:
- dependencies:
- inline-style-parser: 0.2.7
-
- sumchecker@3.0.1:
- dependencies:
- debug: 4.4.3
- transitivePeerDependencies:
- - supports-color
-
- supports-color@7.2.0:
- dependencies:
- has-flag: 4.0.0
-
- supports-preserve-symlinks-flag@1.0.0: {}
-
- symbol-tree@3.2.4: {}
-
- tailwind-merge@3.4.0: {}
-
- tailwindcss@4.1.18: {}
-
- tapable@2.3.0: {}
-
- tar@6.2.1:
- dependencies:
- chownr: 2.0.0
- fs-minipass: 2.1.0
- minipass: 5.0.0
- minizlib: 2.1.2
- mkdirp: 1.0.4
- yallist: 4.0.0
-
- temp-file@3.4.0:
- dependencies:
- async-exit-hook: 2.0.1
- fs-extra: 10.1.0
-
- temp@0.9.4:
- dependencies:
- mkdirp: 0.5.6
- rimraf: 2.6.3
-
- tiny-async-pool@1.3.0:
- dependencies:
- semver: 5.7.2
-
- tiny-typed-emitter@2.1.0: {}
-
- tinybench@2.9.0: {}
-
- tinyexec@1.0.2: {}
-
- tinyglobby@0.2.15:
- dependencies:
- fdir: 6.5.0(picomatch@4.0.3)
- picomatch: 4.0.3
-
- tinyrainbow@3.0.3: {}
-
- tldts-core@6.1.86: {}
-
- tldts@6.1.86:
- dependencies:
- tldts-core: 6.1.86
-
- tmp-promise@3.0.3:
- dependencies:
- tmp: 0.2.5
-
- tmp@0.2.5: {}
-
- to-regex-range@5.0.1:
- dependencies:
- is-number: 7.0.0
-
- tough-cookie@5.1.2:
- dependencies:
- tldts: 6.1.86
-
- tr46@5.1.1:
- dependencies:
- punycode: 2.3.1
-
- trim-lines@3.0.1: {}
-
- trough@2.2.0: {}
-
- truncate-utf8-bytes@1.0.2:
- dependencies:
- utf8-byte-length: 1.0.5
-
- ts-api-utils@2.1.0(typescript@5.9.3):
- dependencies:
- typescript: 5.9.3
-
- tslib@2.8.1: {}
-
- type-check@0.4.0:
- dependencies:
- prelude-ls: 1.2.1
-
- type-fest@0.13.1:
- optional: true
-
- typed-array-buffer@1.0.3:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-typed-array: 1.1.15
-
- typed-array-byte-length@1.0.3:
- dependencies:
- call-bind: 1.0.8
- for-each: 0.3.5
- gopd: 1.2.0
- has-proto: 1.2.0
- is-typed-array: 1.1.15
-
- typed-array-byte-offset@1.0.4:
- dependencies:
- available-typed-arrays: 1.0.7
- call-bind: 1.0.8
- for-each: 0.3.5
- gopd: 1.2.0
- has-proto: 1.2.0
- is-typed-array: 1.1.15
- reflect.getprototypeof: 1.0.10
-
- typed-array-length@1.0.7:
- dependencies:
- call-bind: 1.0.8
- for-each: 0.3.5
- gopd: 1.2.0
- is-typed-array: 1.1.15
- possible-typed-array-names: 1.1.0
- reflect.getprototypeof: 1.0.10
-
- typescript-eslint@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
- dependencies:
- '@typescript-eslint/eslint-plugin': 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/parser': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3)
- '@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.39.2(jiti@2.6.1)
- typescript: 5.9.3
- transitivePeerDependencies:
- - supports-color
-
- typescript@5.9.3: {}
-
- unbox-primitive@1.1.0:
- dependencies:
- call-bound: 1.0.4
- has-bigints: 1.1.0
- has-symbols: 1.1.0
- which-boxed-primitive: 1.1.1
-
- undici-types@6.21.0: {}
-
- undici-types@7.16.0: {}
-
- unified@11.0.5:
- dependencies:
- '@types/unist': 3.0.3
- bail: 2.0.2
- devlop: 1.1.0
- extend: 3.0.2
- is-plain-obj: 4.1.0
- trough: 2.2.0
- vfile: 6.0.3
-
- unique-filename@2.0.1:
- dependencies:
- unique-slug: 3.0.0
-
- unique-slug@3.0.0:
- dependencies:
- imurmurhash: 0.1.4
-
- unist-util-is@6.0.1:
- dependencies:
- '@types/unist': 3.0.3
-
- unist-util-position@5.0.0:
- dependencies:
- '@types/unist': 3.0.3
-
- unist-util-stringify-position@4.0.0:
- dependencies:
- '@types/unist': 3.0.3
-
- unist-util-visit-parents@6.0.2:
- dependencies:
- '@types/unist': 3.0.3
- unist-util-is: 6.0.1
-
- unist-util-visit@5.0.0:
- dependencies:
- '@types/unist': 3.0.3
- unist-util-is: 6.0.1
- unist-util-visit-parents: 6.0.2
-
- universalify@0.1.2: {}
-
- universalify@2.0.1: {}
-
- update-browserslist-db@1.2.3(browserslist@4.28.1):
- dependencies:
- browserslist: 4.28.1
- escalade: 3.2.0
- picocolors: 1.1.1
-
- uri-js@4.4.1:
- dependencies:
- punycode: 2.3.1
-
- use-callback-ref@1.3.3(@types/react@19.2.7)(react@19.2.3):
- dependencies:
- react: 19.2.3
- tslib: 2.8.1
- optionalDependencies:
- '@types/react': 19.2.7
-
- use-sidecar@1.1.3(@types/react@19.2.7)(react@19.2.3):
- dependencies:
- detect-node-es: 1.1.0
- react: 19.2.3
- tslib: 2.8.1
- optionalDependencies:
- '@types/react': 19.2.7
-
- utf8-byte-length@1.0.5: {}
-
- util-deprecate@1.0.2: {}
-
- uuid@13.0.0: {}
-
- verror@1.10.1:
- dependencies:
- assert-plus: 1.0.0
- core-util-is: 1.0.2
- extsprintf: 1.4.1
- optional: true
-
- vfile-message@4.0.3:
- dependencies:
- '@types/unist': 3.0.3
- unist-util-stringify-position: 4.0.0
-
- vfile@6.0.3:
- dependencies:
- '@types/unist': 3.0.3
- vfile-message: 4.0.3
-
- vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2):
- dependencies:
- esbuild: 0.27.2
- fdir: 6.5.0(picomatch@4.0.3)
- picomatch: 4.0.3
- postcss: 8.5.6
- rollup: 4.53.5
- tinyglobby: 0.2.15
- optionalDependencies:
- '@types/node': 25.0.3
- fsevents: 2.3.3
- jiti: 2.6.1
- lightningcss: 1.30.2
- yaml: 2.8.2
-
- vitest@4.0.16(@types/node@25.0.3)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(yaml@2.8.2):
- dependencies:
- '@vitest/expect': 4.0.16
- '@vitest/mocker': 4.0.16(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))
- '@vitest/pretty-format': 4.0.16
- '@vitest/runner': 4.0.16
- '@vitest/snapshot': 4.0.16
- '@vitest/spy': 4.0.16
- '@vitest/utils': 4.0.16
- es-module-lexer: 1.7.0
- expect-type: 1.3.0
- magic-string: 0.30.21
- obug: 2.1.1
- pathe: 2.0.3
- picomatch: 4.0.3
- std-env: 3.10.0
- tinybench: 2.9.0
- tinyexec: 1.0.2
- tinyglobby: 0.2.15
- tinyrainbow: 3.0.3
- vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)
- why-is-node-running: 2.3.0
- optionalDependencies:
- '@types/node': 25.0.3
- jsdom: 26.1.0
- transitivePeerDependencies:
- - jiti
- - less
- - lightningcss
- - msw
- - sass
- - sass-embedded
- - stylus
- - sugarss
- - terser
- - tsx
- - yaml
-
- w3c-xmlserializer@5.0.0:
- dependencies:
- xml-name-validator: 5.0.0
-
- wcwidth@1.0.1:
- dependencies:
- defaults: 1.0.4
-
- webidl-conversions@7.0.0: {}
-
- whatwg-encoding@3.1.1:
- dependencies:
- iconv-lite: 0.6.3
-
- whatwg-mimetype@4.0.0: {}
-
- whatwg-url@14.2.0:
- dependencies:
- tr46: 5.1.1
- webidl-conversions: 7.0.0
-
- which-boxed-primitive@1.1.1:
- dependencies:
- is-bigint: 1.1.0
- is-boolean-object: 1.2.2
- is-number-object: 1.1.1
- is-string: 1.1.1
- is-symbol: 1.1.1
-
- which-builtin-type@1.2.1:
- dependencies:
- call-bound: 1.0.4
- function.prototype.name: 1.1.8
- has-tostringtag: 1.0.2
- is-async-function: 2.1.1
- is-date-object: 1.1.0
- is-finalizationregistry: 1.1.1
- is-generator-function: 1.1.2
- is-regex: 1.2.1
- is-weakref: 1.1.1
- isarray: 2.0.5
- which-boxed-primitive: 1.1.1
- which-collection: 1.0.2
- which-typed-array: 1.1.19
-
- which-collection@1.0.2:
- dependencies:
- is-map: 2.0.3
- is-set: 2.0.3
- is-weakmap: 2.0.2
- is-weakset: 2.0.4
-
- which-typed-array@1.1.19:
- dependencies:
- available-typed-arrays: 1.0.7
- call-bind: 1.0.8
- call-bound: 1.0.4
- for-each: 0.3.5
- get-proto: 1.0.1
- gopd: 1.2.0
- has-tostringtag: 1.0.2
-
- which@2.0.2:
- dependencies:
- isexe: 2.0.0
-
- why-is-node-running@2.3.0:
- dependencies:
- siginfo: 2.0.0
- stackback: 0.0.2
-
- word-wrap@1.2.5: {}
-
- wrap-ansi@7.0.0:
- dependencies:
- ansi-styles: 4.3.0
- string-width: 4.2.3
- strip-ansi: 6.0.1
-
- wrap-ansi@8.1.0:
- dependencies:
- ansi-styles: 6.2.3
- string-width: 5.1.2
- strip-ansi: 7.1.2
-
- wrap-ansi@9.0.2:
- dependencies:
- ansi-styles: 6.2.3
- string-width: 7.2.0
- strip-ansi: 7.1.2
-
- wrappy@1.0.2: {}
-
- ws@8.18.3: {}
-
- xml-name-validator@5.0.0: {}
-
- xmlbuilder@15.1.1: {}
-
- xmlchars@2.2.0: {}
-
- y18n@5.0.8: {}
-
- yallist@3.1.1: {}
-
- yallist@4.0.0: {}
-
- yaml@2.8.2: {}
-
- yargs-parser@21.1.1: {}
-
- yargs@17.7.2:
- dependencies:
- cliui: 8.0.1
- escalade: 3.2.0
- get-caller-file: 2.0.5
- require-directory: 2.1.1
- string-width: 4.2.3
- y18n: 5.0.8
- yargs-parser: 21.1.1
-
- yauzl@2.10.0:
- dependencies:
- buffer-crc32: 0.2.13
- fd-slicer: 1.1.0
-
- yocto-queue@0.1.0: {}
-
- zod-validation-error@4.0.2(zod@4.2.1):
- dependencies:
- zod: 4.2.1
-
- zod@4.2.1: {}
-
- zustand@5.0.9(@types/react@19.2.7)(react@19.2.3):
- optionalDependencies:
- '@types/react': 19.2.7
- react: 19.2.3
-
- zwitch@2.0.4: {}
diff --git a/auto-claude-ui/src/main/agent-manager.ts.backup b/auto-claude-ui/src/main/agent-manager.ts.backup
deleted file mode 100644
index 0436a024..00000000
--- a/auto-claude-ui/src/main/agent-manager.ts.backup
+++ /dev/null
@@ -1,1101 +0,0 @@
-import { spawn, ChildProcess } from 'child_process';
-import { EventEmitter } from 'events';
-import path from 'path';
-import { existsSync, readFileSync } from 'fs';
-import { app } from 'electron';
-import { projectStore } from './project-store';
-import { detectRateLimit, createSDKRateLimitInfo, getProfileEnv } from './rate-limit-detector';
-
-interface AgentProcess {
- taskId: string;
- process: ChildProcess;
- startedAt: Date;
- projectPath?: string; // For ideation processes to load session on completion
- spawnId: number; // Unique ID to identify this specific spawn
-}
-
-export interface ExecutionProgressData {
- phase: 'idle' | 'planning' | 'coding' | 'qa_review' | 'qa_fixing' | 'complete' | 'failed';
- phaseProgress: number;
- overallProgress: number;
- currentSubtask?: string;
- message?: string;
-}
-
-export type ProcessType = 'spec-creation' | 'task-execution' | 'qa-process';
-
-export interface AgentManagerEvents {
- log: (taskId: string, log: string) => void;
- error: (taskId: string, error: string) => void;
- exit: (taskId: string, code: number | null, processType: ProcessType) => void;
- 'execution-progress': (taskId: string, progress: ExecutionProgressData) => void;
-}
-
-/**
- * Manages Python subprocess spawning for auto-claude agents
- */
-export class AgentManager extends EventEmitter {
- private processes: Map = new Map();
- private killedSpawnIds: Set = new Set(); // Track spawn IDs whose processes were killed
- private spawnCounter: number = 0; // Unique ID for each spawn
- private pythonPath: string = 'python3';
- private autoBuildSourcePath: string = ''; // Source auto-claude repo location
-
- constructor() {
- super();
- }
-
- /**
- * Configure paths for Python and auto-claude source
- */
- configure(pythonPath?: string, autoBuildSourcePath?: string): void {
- if (pythonPath) {
- this.pythonPath = pythonPath;
- }
- if (autoBuildSourcePath) {
- this.autoBuildSourcePath = autoBuildSourcePath;
- }
- }
-
- /**
- * Get the auto-claude source path (detects automatically if not configured)
- */
- private getAutoBuildSourcePath(): string | null {
- // If manually configured, use that
- if (this.autoBuildSourcePath && existsSync(this.autoBuildSourcePath)) {
- return this.autoBuildSourcePath;
- }
-
- // Auto-detect from app location
- const possiblePaths = [
- // Dev mode: from dist/main -> ../../auto-claude (sibling to auto-claude-ui)
- path.resolve(__dirname, '..', '..', '..', 'auto-claude'),
- // Alternative: from app root
- path.resolve(app.getAppPath(), '..', 'auto-claude'),
- // If running from repo root
- path.resolve(process.cwd(), 'auto-claude')
- ];
-
- for (const p of possiblePaths) {
- if (existsSync(p) && existsSync(path.join(p, 'VERSION'))) {
- return p;
- }
- }
- return null;
- }
-
- /**
- * Get project-specific environment variables based on project settings
- */
- private getProjectEnvVars(projectPath: string): Record {
- const env: Record = {};
-
- // Find project by path
- const projects = projectStore.getProjects();
- const project = projects.find((p) => p.path === projectPath);
-
- if (project?.settings) {
- // Graphiti MCP integration
- if (project.settings.graphitiMcpEnabled) {
- const graphitiUrl = project.settings.graphitiMcpUrl || 'http://localhost:8000/mcp/';
- env['GRAPHITI_MCP_URL'] = graphitiUrl;
- }
- }
-
- return env;
- }
-
- /**
- * Load environment variables from auto-claude .env file
- */
- private loadAutoBuildEnv(): Record {
- const autoBuildSource = this.getAutoBuildSourcePath();
- if (!autoBuildSource) {
- console.log('[loadAutoBuildEnv] No auto-build source path found');
- return {};
- }
-
- const envPath = path.join(autoBuildSource, '.env');
- console.log('[loadAutoBuildEnv] Looking for .env at:', envPath);
- if (!existsSync(envPath)) {
- console.log('[loadAutoBuildEnv] .env file does not exist');
- return {};
- }
-
- try {
- const envContent = readFileSync(envPath, 'utf-8');
- const envVars: Record = {};
-
- // Handle both Unix (\n) and Windows (\r\n) line endings
- for (const line of envContent.split(/\r?\n/)) {
- const trimmed = line.trim();
- // Skip comments and empty lines
- if (!trimmed || trimmed.startsWith('#')) {
- continue;
- }
-
- const eqIndex = trimmed.indexOf('=');
- if (eqIndex > 0) {
- const key = trimmed.substring(0, eqIndex).trim();
- let value = trimmed.substring(eqIndex + 1).trim();
-
- // Remove quotes if present
- if ((value.startsWith('"') && value.endsWith('"')) ||
- (value.startsWith("'") && value.endsWith("'"))) {
- value = value.slice(1, -1);
- }
-
- envVars[key] = value;
- }
- }
-
- return envVars;
- } catch {
- return {};
- }
- }
-
- /**
- * Start spec creation process
- */
- startSpecCreation(
- taskId: string,
- projectPath: string,
- taskDescription: string,
- specDir?: string, // Optional spec directory (when task already has a directory created by UI)
- metadata?: { requireReviewBeforeCoding?: boolean } // Task metadata to check for review requirement
- ): void {
- // Use source auto-claude path (the repo), not the project's auto-claude
- const autoBuildSource = this.getAutoBuildSourcePath();
-
- if (!autoBuildSource) {
- this.emit('error', taskId, 'Auto-build source path not found. Please configure it in App Settings.');
- return;
- }
-
- const specRunnerPath = path.join(autoBuildSource, 'spec_runner.py');
-
- if (!existsSync(specRunnerPath)) {
- this.emit('error', taskId, `Spec runner not found at: ${specRunnerPath}`);
- return;
- }
-
- // Load environment variables from auto-claude .env file and project settings
- const autoBuildEnv = this.loadAutoBuildEnv();
- const projectEnv = this.getProjectEnvVars(projectPath);
- const combinedEnv = { ...autoBuildEnv, ...projectEnv };
-
- // spec_runner.py will auto-start run.py after spec creation completes
- const args = [specRunnerPath, '--task', taskDescription, '--project-dir', projectPath];
-
- // Pass spec directory if provided (for UI-created tasks that already have a directory)
- if (specDir) {
- args.push('--spec-dir', specDir);
- }
-
- // Check if user requires review before coding
- // If requireReviewBeforeCoding is true, skip auto-approve to trigger review checkpoint
- if (!metadata?.requireReviewBeforeCoding) {
- // Auto-approve: When user starts a task from the UI without requiring review, that IS their approval
- // No need for interactive review checkpoint - user explicitly clicked "Start"
- args.push('--auto-approve');
- }
- // If requireReviewBeforeCoding is true, don't add --auto-approve, allowing the review checkpoint to appear
-
- // Note: This is spec-creation but it chains to task-execution via run.py
- // So we treat the whole thing as task-execution for status purposes
- this.spawnProcess(taskId, autoBuildSource, args, combinedEnv, 'task-execution');
- }
-
- /**
- * Start task execution (run.py)
- */
- startTaskExecution(
- taskId: string,
- projectPath: string,
- specId: string,
- options: { parallel?: boolean; workers?: number } = {}
- ): void {
- console.log('[AgentManager] startTaskExecution called for:', taskId, specId);
- // Use source auto-claude path (the repo), not the project's auto-claude
- const autoBuildSource = this.getAutoBuildSourcePath();
-
- if (!autoBuildSource) {
- console.log('[AgentManager] ERROR: Auto-build source path not found');
- this.emit('error', taskId, 'Auto-build source path not found. Please configure it in App Settings.');
- return;
- }
-
- const runPath = path.join(autoBuildSource, 'run.py');
- console.log('[AgentManager] runPath:', runPath);
-
- if (!existsSync(runPath)) {
- console.log('[AgentManager] ERROR: Run script not found at:', runPath);
- this.emit('error', taskId, `Run script not found at: ${runPath}`);
- return;
- }
-
- // Load environment variables from auto-claude .env file and project settings
- const autoBuildEnv = this.loadAutoBuildEnv();
- const projectEnv = this.getProjectEnvVars(projectPath);
- const combinedEnv = { ...autoBuildEnv, ...projectEnv };
-
- const args = [runPath, '--spec', specId, '--project-dir', projectPath];
-
- // Always use auto-continue when running from UI (non-interactive)
- args.push('--auto-continue');
-
- // Force: When user starts a task from the UI, that IS their approval
- // The review checkpoint is for CLI users who need to review before building
- // UI users have already seen the spec in the interface before clicking "Start"
- args.push('--force');
-
- if (options.parallel && options.workers) {
- args.push('--parallel', options.workers.toString());
- }
-
- console.log('[AgentManager] Spawning process with args:', args);
- this.spawnProcess(taskId, autoBuildSource, args, combinedEnv, 'task-execution');
- }
-
- /**
- * Start QA process
- */
- startQAProcess(
- taskId: string,
- projectPath: string,
- specId: string
- ): void {
- // Use source auto-claude path (the repo), not the project's auto-claude
- const autoBuildSource = this.getAutoBuildSourcePath();
-
- if (!autoBuildSource) {
- this.emit('error', taskId, 'Auto-build source path not found. Please configure it in App Settings.');
- return;
- }
-
- const runPath = path.join(autoBuildSource, 'run.py');
-
- if (!existsSync(runPath)) {
- this.emit('error', taskId, `Run script not found at: ${runPath}`);
- return;
- }
-
- // Load environment variables from auto-claude .env file and project settings
- const autoBuildEnv = this.loadAutoBuildEnv();
- const projectEnv = this.getProjectEnvVars(projectPath);
- const combinedEnv = { ...autoBuildEnv, ...projectEnv };
-
- const args = [runPath, '--spec', specId, '--project-dir', projectPath, '--qa'];
-
- this.spawnProcess(taskId, autoBuildSource, args, combinedEnv, 'qa-process');
- }
-
- /**
- * Start roadmap generation process
- */
- startRoadmapGeneration(
- projectId: string,
- projectPath: string,
- refresh: boolean = false
- ): void {
- // Use source auto-claude path (the repo), not the project's auto-claude
- const autoBuildSource = this.getAutoBuildSourcePath();
-
- if (!autoBuildSource) {
- this.emit('roadmap-error', projectId, 'Auto-build source path not found. Please configure it in App Settings.');
- return;
- }
-
- const roadmapRunnerPath = path.join(autoBuildSource, 'roadmap_runner.py');
-
- if (!existsSync(roadmapRunnerPath)) {
- this.emit('roadmap-error', projectId, `Roadmap runner not found at: ${roadmapRunnerPath}`);
- return;
- }
-
- const args = [roadmapRunnerPath, '--project', projectPath];
-
- if (refresh) {
- args.push('--refresh');
- }
-
- // Use projectId as taskId for roadmap operations
- this.spawnRoadmapProcess(projectId, projectPath, args);
- }
-
- /**
- * Start ideation generation process
- */
- startIdeationGeneration(
- projectId: string,
- projectPath: string,
- config: {
- enabledTypes: string[];
- includeRoadmapContext: boolean;
- includeKanbanContext: boolean;
- maxIdeasPerType: number;
- append?: boolean;
- },
- refresh: boolean = false
- ): void {
- // Use source auto-claude path (the repo), not the project's auto-claude
- const autoBuildSource = this.getAutoBuildSourcePath();
-
- if (!autoBuildSource) {
- this.emit('ideation-error', projectId, 'Auto-build source path not found. Please configure it in App Settings.');
- return;
- }
-
- const ideationRunnerPath = path.join(autoBuildSource, 'ideation_runner.py');
-
- if (!existsSync(ideationRunnerPath)) {
- this.emit('ideation-error', projectId, `Ideation runner not found at: ${ideationRunnerPath}`);
- return;
- }
-
- const args = [ideationRunnerPath, '--project', projectPath];
-
- // Add enabled types as comma-separated list
- if (config.enabledTypes.length > 0) {
- args.push('--types', config.enabledTypes.join(','));
- }
-
- // Add context flags (script uses --no-roadmap/--no-kanban negative flags)
- if (!config.includeRoadmapContext) {
- args.push('--no-roadmap');
- }
- if (!config.includeKanbanContext) {
- args.push('--no-kanban');
- }
-
- // Add max ideas per type
- if (config.maxIdeasPerType) {
- args.push('--max-ideas', config.maxIdeasPerType.toString());
- }
-
- if (refresh) {
- args.push('--refresh');
- }
-
- // Add append flag to preserve existing ideas
- if (config.append) {
- args.push('--append');
- }
-
- // Use projectId as taskId for ideation operations
- this.spawnIdeationProcess(projectId, projectPath, args);
- }
-
- /**
- * Spawn a Python process for ideation generation
- */
- private spawnIdeationProcess(
- projectId: string,
- projectPath: string,
- args: string[]
- ): void {
- // Kill existing process for this project if any
- this.killTask(projectId);
-
- // Generate unique spawn ID for this process instance
- const spawnId = ++this.spawnCounter;
-
- // Run from auto-claude source directory so imports work correctly
- const autoBuildSource = this.getAutoBuildSourcePath();
- const cwd = autoBuildSource || process.cwd();
-
- // Load environment variables from auto-claude .env file and project settings
- const autoBuildEnv = this.loadAutoBuildEnv();
- const projectEnv = this.getProjectEnvVars(projectPath);
- const combinedEnv = { ...autoBuildEnv, ...projectEnv };
-
- // Get active Claude profile environment (CLAUDE_CONFIG_DIR if not default)
- const profileEnv = getProfileEnv();
-
- const childProcess = spawn(this.pythonPath, args, {
- cwd,
- env: {
- ...process.env,
- ...combinedEnv, // Include auto-claude .env variables and project-specific env vars
- ...profileEnv, // Include active Claude profile config
- PYTHONUNBUFFERED: '1'
- }
- });
-
- this.processes.set(projectId, {
- taskId: projectId,
- process: childProcess,
- startedAt: new Date(),
- projectPath, // Store project path for loading session on completion
- spawnId
- });
-
- // Track progress through output
- let progressPhase = 'analyzing';
- let progressPercent = 10;
- // Collect output for rate limit detection
- let allOutput = '';
-
- // Helper to emit logs - split multi-line output into individual log lines
- const emitLogs = (log: string) => {
- const lines = log.split('\n').filter(line => line.trim().length > 0);
- for (const line of lines) {
- const trimmed = line.trim();
- if (trimmed.length > 0) {
- console.log('[Ideation]', trimmed);
- this.emit('ideation-log', projectId, trimmed);
- }
- }
- };
-
- console.log('[Ideation] Starting ideation process with args:', args);
- console.log('[Ideation] CWD:', cwd);
- console.log('[Ideation] Python path:', this.pythonPath);
- console.log('[Ideation] Env vars loaded:', Object.keys(autoBuildEnv));
- console.log('[Ideation] Has CLAUDE_CODE_OAUTH_TOKEN:', !!autoBuildEnv['CLAUDE_CODE_OAUTH_TOKEN']);
-
- // Track completed types for progress calculation
- const completedTypes = new Set();
- const totalTypes = args.filter(a => a !== '--types').length > 0 ? 7 : 7; // Default all types
-
- // Handle stdout
- childProcess.stdout?.on('data', (data: Buffer) => {
- const log = data.toString();
- // Collect output for rate limit detection (keep last 10KB)
- allOutput = (allOutput + log).slice(-10000);
-
- // Emit all log lines for the activity log
- emitLogs(log);
-
- // Check for streaming type completion signals
- const typeCompleteMatch = log.match(/IDEATION_TYPE_COMPLETE:(\w+):(\d+)/);
- if (typeCompleteMatch) {
- const [, ideationType, ideasCount] = typeCompleteMatch;
- completedTypes.add(ideationType);
- console.log(`[Ideation] Type complete: ${ideationType} with ${ideasCount} ideas`);
-
- // Emit event for UI to load this type's ideas immediately
- this.emit('ideation-type-complete', projectId, ideationType, parseInt(ideasCount, 10));
- }
-
- const typeFailedMatch = log.match(/IDEATION_TYPE_FAILED:(\w+)/);
- if (typeFailedMatch) {
- const [, ideationType] = typeFailedMatch;
- completedTypes.add(ideationType);
- console.log(`[Ideation] Type failed: ${ideationType}`);
- this.emit('ideation-type-failed', projectId, ideationType);
- }
-
- // Parse progress from output - track phase transitions
- if (log.includes('PROJECT INDEX') || log.includes('PROJECT ANALYSIS')) {
- progressPhase = 'analyzing';
- progressPercent = 10;
- } else if (log.includes('CONTEXT GATHERING')) {
- progressPhase = 'discovering';
- progressPercent = 20;
- } else if (log.includes('GENERATING IDEAS (PARALLEL)') || log.includes('Starting') && log.includes('ideation agents in parallel')) {
- progressPhase = 'generating';
- progressPercent = 30;
- } else if (log.includes('MERGE') || log.includes('FINALIZE')) {
- progressPhase = 'finalizing';
- progressPercent = 90;
- } else if (log.includes('IDEATION COMPLETE')) {
- progressPhase = 'complete';
- progressPercent = 100;
- }
-
- // Update progress based on completed types during generation phase
- if (progressPhase === 'generating' && completedTypes.size > 0) {
- // Progress from 30% to 90% based on completed types
- progressPercent = 30 + Math.floor((completedTypes.size / totalTypes) * 60);
- }
-
- // Emit progress update with a clean message for the status bar
- const statusMessage = log.trim().split('\n')[0].substring(0, 200);
- this.emit('ideation-progress', projectId, {
- phase: progressPhase,
- progress: progressPercent,
- message: statusMessage,
- completedTypes: Array.from(completedTypes)
- });
- });
-
- // Handle stderr - also emit as logs
- childProcess.stderr?.on('data', (data: Buffer) => {
- const log = data.toString();
- // Collect stderr for rate limit detection too
- allOutput = (allOutput + log).slice(-10000);
- console.error('[Ideation STDERR]', log);
- emitLogs(log);
- this.emit('ideation-progress', projectId, {
- phase: progressPhase,
- progress: progressPercent,
- message: log.trim().split('\n')[0].substring(0, 200)
- });
- });
-
- // Handle process exit
- childProcess.on('exit', (code: number | null) => {
- console.log('[Ideation] Process exited with code:', code);
-
- // Get the stored project path before deleting from map
- const processInfo = this.processes.get(projectId);
- const storedProjectPath = processInfo?.projectPath;
- this.processes.delete(projectId);
-
- // Check for rate limit if process failed
- if (code !== 0) {
- const rateLimitDetection = detectRateLimit(allOutput);
- if (rateLimitDetection.isRateLimited) {
- console.log('[Ideation] Rate limit detected:', {
- projectId,
- resetTime: rateLimitDetection.resetTime,
- limitType: rateLimitDetection.limitType,
- suggestedProfile: rateLimitDetection.suggestedProfile?.name
- });
-
- const rateLimitInfo = createSDKRateLimitInfo('ideation', rateLimitDetection, {
- projectId
- });
- this.emit('sdk-rate-limit', rateLimitInfo);
- }
- }
-
- if (code === 0) {
- this.emit('ideation-progress', projectId, {
- phase: 'complete',
- progress: 100,
- message: 'Ideation generation complete'
- });
-
- // Load and emit the complete ideation session
- if (storedProjectPath) {
- try {
- const ideationFilePath = path.join(
- storedProjectPath,
- '.auto-claude',
- 'ideation',
- 'ideation.json'
- );
- if (existsSync(ideationFilePath)) {
- const content = readFileSync(ideationFilePath, 'utf-8');
- const session = JSON.parse(content);
- console.log('[Ideation] Emitting ideation-complete with session data');
- this.emit('ideation-complete', projectId, session);
- } else {
- console.warn('[Ideation] ideation.json not found at:', ideationFilePath);
- }
- } catch (err) {
- console.error('[Ideation] Failed to load ideation session:', err);
- }
- }
- } else {
- this.emit('ideation-error', projectId, `Ideation generation failed with exit code ${code}`);
- }
- });
-
- // Handle process error
- childProcess.on('error', (err: Error) => {
- console.error('[Ideation] Process error:', err.message);
- this.processes.delete(projectId);
- this.emit('ideation-error', projectId, err.message);
- });
- }
-
- /**
- * Spawn a Python process for roadmap generation
- */
- private spawnRoadmapProcess(
- projectId: string,
- projectPath: string,
- args: string[]
- ): void {
- // Kill existing process for this project if any
- this.killTask(projectId);
-
- // Generate unique spawn ID for this process instance
- const spawnId = ++this.spawnCounter;
-
- // Run from auto-claude source directory so imports work correctly
- const autoBuildSource = this.getAutoBuildSourcePath();
- const cwd = autoBuildSource || process.cwd();
-
- // Load environment variables from auto-claude .env file and project settings
- const autoBuildEnv = this.loadAutoBuildEnv();
- const projectEnv = this.getProjectEnvVars(projectPath);
- const combinedEnv = { ...autoBuildEnv, ...projectEnv };
-
- // Get active Claude profile environment (CLAUDE_CONFIG_DIR if not default)
- const ideationProfileEnv = getProfileEnv();
-
- const childProcess = spawn(this.pythonPath, args, {
- cwd,
- env: {
- ...process.env,
- ...combinedEnv, // Include auto-claude .env variables and project-specific env vars
- ...ideationProfileEnv, // Include active Claude profile config
- PYTHONUNBUFFERED: '1'
- }
- });
-
- this.processes.set(projectId, {
- taskId: projectId,
- process: childProcess,
- startedAt: new Date(),
- spawnId
- });
-
- // Track progress through output
- let progressPhase = 'analyzing';
- let progressPercent = 10;
- // Collect output for rate limit detection
- let allRoadmapOutput = '';
-
- // Handle stdout
- childProcess.stdout?.on('data', (data: Buffer) => {
- const log = data.toString();
- // Collect output for rate limit detection (keep last 10KB)
- allRoadmapOutput = (allRoadmapOutput + log).slice(-10000);
-
- // Parse progress from output
- if (log.includes('PROJECT ANALYSIS')) {
- progressPhase = 'analyzing';
- progressPercent = 20;
- } else if (log.includes('PROJECT DISCOVERY')) {
- progressPhase = 'discovering';
- progressPercent = 40;
- } else if (log.includes('FEATURE GENERATION')) {
- progressPhase = 'generating';
- progressPercent = 70;
- } else if (log.includes('ROADMAP GENERATED')) {
- progressPhase = 'complete';
- progressPercent = 100;
- }
-
- // Emit progress update
- this.emit('roadmap-progress', projectId, {
- phase: progressPhase,
- progress: progressPercent,
- message: log.trim().substring(0, 200) // Truncate long messages
- });
- });
-
- // Handle stderr
- childProcess.stderr?.on('data', (data: Buffer) => {
- const log = data.toString();
- // Collect stderr for rate limit detection too
- allRoadmapOutput = (allRoadmapOutput + log).slice(-10000);
- this.emit('roadmap-progress', projectId, {
- phase: progressPhase,
- progress: progressPercent,
- message: log.trim().substring(0, 200)
- });
- });
-
- // Handle process exit
- childProcess.on('exit', (code: number | null) => {
- this.processes.delete(projectId);
-
- // Check for rate limit if process failed
- if (code !== 0) {
- const rateLimitDetection = detectRateLimit(allRoadmapOutput);
- if (rateLimitDetection.isRateLimited) {
- console.log('[Roadmap] Rate limit detected:', {
- projectId,
- resetTime: rateLimitDetection.resetTime,
- limitType: rateLimitDetection.limitType,
- suggestedProfile: rateLimitDetection.suggestedProfile?.name
- });
-
- const rateLimitInfo = createSDKRateLimitInfo('roadmap', rateLimitDetection, {
- projectId
- });
- this.emit('sdk-rate-limit', rateLimitInfo);
- }
- }
-
- if (code === 0) {
- this.emit('roadmap-progress', projectId, {
- phase: 'complete',
- progress: 100,
- message: 'Roadmap generation complete'
- });
- } else {
- this.emit('roadmap-error', projectId, `Roadmap generation failed with exit code ${code}`);
- }
- });
-
- // Handle process error
- childProcess.on('error', (err: Error) => {
- this.processes.delete(projectId);
- this.emit('roadmap-error', projectId, err.message);
- });
- }
-
- /**
- * Parse log output to detect execution phase transitions
- */
- private parseExecutionPhase(
- log: string,
- currentPhase: ExecutionProgressData['phase'],
- isSpecRunner: boolean
- ): { phase: ExecutionProgressData['phase']; message?: string; currentSubtask?: string } | null {
- const lowerLog = log.toLowerCase();
-
- // Spec runner phase detection (all part of "planning")
- if (isSpecRunner) {
- if (lowerLog.includes('discovering') || lowerLog.includes('discovery')) {
- return { phase: 'planning', message: 'Discovering project context...' };
- }
- if (lowerLog.includes('requirements') || lowerLog.includes('gathering')) {
- return { phase: 'planning', message: 'Gathering requirements...' };
- }
- if (lowerLog.includes('writing spec') || lowerLog.includes('spec writer')) {
- return { phase: 'planning', message: 'Writing specification...' };
- }
- if (lowerLog.includes('validating') || lowerLog.includes('validation')) {
- return { phase: 'planning', message: 'Validating specification...' };
- }
- if (lowerLog.includes('spec complete') || lowerLog.includes('specification complete')) {
- return { phase: 'planning', message: 'Specification complete' };
- }
- }
-
- // Run.py phase detection
- // Planner agent running
- if (lowerLog.includes('planner agent') || lowerLog.includes('creating implementation plan')) {
- return { phase: 'planning', message: 'Creating implementation plan...' };
- }
-
- // Coder agent running
- if (lowerLog.includes('coder agent') || lowerLog.includes('starting coder')) {
- return { phase: 'coding', message: 'Implementing code changes...' };
- }
-
- // Subtask progress detection
- const subtaskMatch = log.match(/subtask[:\s]+(\d+(?:\/\d+)?|\w+[-_]\w+)/i);
- if (subtaskMatch && currentPhase === 'coding') {
- return { phase: 'coding', currentSubtask: subtaskMatch[1], message: `Working on subtask ${subtaskMatch[1]}...` };
- }
-
- // Subtask completion detection
- if (lowerLog.includes('subtask completed') || lowerLog.includes('subtask done')) {
- const completedSubtask = log.match(/subtask[:\s]+"?([^"]+)"?\s+completed/i);
- return {
- phase: 'coding',
- currentSubtask: completedSubtask?.[1],
- message: `Subtask ${completedSubtask?.[1] || ''} completed`
- };
- }
-
- // QA Review phase
- if (lowerLog.includes('qa reviewer') || lowerLog.includes('qa_reviewer') || lowerLog.includes('starting qa')) {
- return { phase: 'qa_review', message: 'Running QA review...' };
- }
-
- // QA Fixer phase
- if (lowerLog.includes('qa fixer') || lowerLog.includes('qa_fixer') || lowerLog.includes('fixing issues')) {
- return { phase: 'qa_fixing', message: 'Fixing QA issues...' };
- }
-
- // Completion detection - be conservative, require explicit success markers
- // The AI agent prints "=== BUILD COMPLETE ===" when truly done (from coder.md)
- // Only trust this pattern, not generic "all subtasks completed" which could be false positive
- if (lowerLog.includes('=== build complete ===') || lowerLog.includes('qa passed')) {
- return { phase: 'complete', message: 'Build completed successfully' };
- }
-
- // "All subtasks completed" is informational - don't change phase based on this alone
- // The coordinator may print this even when subtasks are blocked, so we stay in coding phase
- // and let the actual implementation_plan.json status drive the UI
- if (lowerLog.includes('all subtasks completed')) {
- return { phase: 'coding', message: 'Subtasks marked complete' };
- }
-
- // Incomplete build detection - when coordinator exits with pending subtasks
- if (lowerLog.includes('build incomplete') || lowerLog.includes('subtasks still pending')) {
- return { phase: 'coding', message: 'Build paused - subtasks still pending' };
- }
-
- // Error/failure detection
- if (lowerLog.includes('build failed') || lowerLog.includes('error:') || lowerLog.includes('fatal')) {
- return { phase: 'failed', message: log.trim().substring(0, 200) };
- }
-
- return null;
- }
-
- /**
- * Calculate overall progress based on phase and phase progress
- */
- private calculateOverallProgress(phase: ExecutionProgressData['phase'], phaseProgress: number): number {
- // Phase weight ranges (same as in constants.ts)
- const weights: Record = {
- idle: { start: 0, end: 0 },
- planning: { start: 0, end: 20 },
- coding: { start: 20, end: 80 },
- qa_review: { start: 80, end: 95 },
- qa_fixing: { start: 80, end: 95 },
- complete: { start: 100, end: 100 },
- failed: { start: 0, end: 0 }
- };
-
- const phaseWeight = weights[phase] || { start: 0, end: 0 };
- const phaseRange = phaseWeight.end - phaseWeight.start;
- return Math.round(phaseWeight.start + (phaseRange * phaseProgress / 100));
- }
-
- /**
- * Spawn a Python process
- */
- private spawnProcess(
- taskId: string,
- cwd: string,
- args: string[],
- extraEnv: Record = {},
- processType: ProcessType = 'task-execution'
- ): void {
- const isSpecRunner = processType === 'spec-creation';
- // Kill existing process for this task if any
- this.killTask(taskId);
-
- // Generate unique spawn ID for this process instance
- const spawnId = ++this.spawnCounter;
-
- console.log('[spawnProcess] Spawning with pythonPath:', this.pythonPath);
- console.log('[spawnProcess] cwd:', cwd);
- console.log('[spawnProcess] processType:', processType);
- console.log('[spawnProcess] spawnId:', spawnId);
-
- // Get active Claude profile environment (CLAUDE_CONFIG_DIR if not default)
- const spawnProfileEnv = getProfileEnv();
-
- const childProcess = spawn(this.pythonPath, args, {
- cwd,
- env: {
- ...process.env,
- ...extraEnv,
- ...spawnProfileEnv, // Include active Claude profile config
- PYTHONUNBUFFERED: '1' // Ensure real-time output
- }
- });
-
- console.log('[spawnProcess] Process spawned, pid:', childProcess.pid);
-
- this.processes.set(taskId, {
- taskId,
- process: childProcess,
- startedAt: new Date(),
- spawnId
- });
-
- // Track execution progress
- let currentPhase: ExecutionProgressData['phase'] = isSpecRunner ? 'planning' : 'planning';
- let phaseProgress = 0;
- let currentSubtask: string | undefined;
- let lastMessage: string | undefined;
- // Collect all output for rate limit detection
- let allOutput = '';
-
- // Emit initial progress
- this.emit('execution-progress', taskId, {
- phase: currentPhase,
- phaseProgress: 0,
- overallProgress: this.calculateOverallProgress(currentPhase, 0),
- message: isSpecRunner ? 'Starting spec creation...' : 'Starting build process...'
- });
-
- const processLog = (log: string) => {
- // Collect output for rate limit detection (keep last 10KB)
- allOutput = (allOutput + log).slice(-10000);
- // Parse for phase transitions
- const phaseUpdate = this.parseExecutionPhase(log, currentPhase, isSpecRunner);
-
- if (phaseUpdate) {
- const phaseChanged = phaseUpdate.phase !== currentPhase;
- currentPhase = phaseUpdate.phase;
-
- if (phaseUpdate.currentSubtask) {
- currentSubtask = phaseUpdate.currentSubtask;
- }
- if (phaseUpdate.message) {
- lastMessage = phaseUpdate.message;
- }
-
- // Reset phase progress on phase change, otherwise increment
- if (phaseChanged) {
- phaseProgress = 10; // Start new phase at 10%
- } else {
- phaseProgress = Math.min(90, phaseProgress + 5); // Increment within phase
- }
-
- const overallProgress = this.calculateOverallProgress(currentPhase, phaseProgress);
-
- this.emit('execution-progress', taskId, {
- phase: currentPhase,
- phaseProgress,
- overallProgress,
- currentSubtask,
- message: lastMessage
- });
- }
- };
-
- // Handle stdout
- childProcess.stdout?.on('data', (data: Buffer) => {
- const log = data.toString();
- console.log('[spawnProcess] stdout:', log.substring(0, 200));
- this.emit('log', taskId, log);
- processLog(log);
- });
-
- // Handle stderr
- childProcess.stderr?.on('data', (data: Buffer) => {
- const log = data.toString();
- console.log('[spawnProcess] stderr:', log.substring(0, 200));
- // Some Python output goes to stderr (like progress bars)
- // so we treat it as log, not error
- this.emit('log', taskId, log);
- processLog(log);
- });
-
- // Handle process exit
- childProcess.on('exit', (code: number | null) => {
- console.log('[spawnProcess] Process exited with code:', code, 'spawnId:', spawnId);
- this.processes.delete(taskId);
-
- // Check if this specific spawn was killed (vs exited naturally)
- // If killed, don't emit exit event to prevent race condition with new process
- if (this.killedSpawnIds.has(spawnId)) {
- console.log('[spawnProcess] Process was killed, skipping exit event for spawnId:', spawnId);
- this.killedSpawnIds.delete(spawnId);
- return;
- }
-
- // Check for rate limit if process failed
- if (code !== 0) {
- const rateLimitDetection = detectRateLimit(allOutput);
- if (rateLimitDetection.isRateLimited) {
- console.log('[spawnProcess] Rate limit detected in task output:', {
- taskId,
- resetTime: rateLimitDetection.resetTime,
- limitType: rateLimitDetection.limitType,
- suggestedProfile: rateLimitDetection.suggestedProfile?.name
- });
-
- // Determine source type based on processType
- const source = processType === 'spec-creation' ? 'task' : 'task';
-
- // Emit rate limit event
- const rateLimitInfo = createSDKRateLimitInfo(source, rateLimitDetection, {
- taskId
- });
- this.emit('sdk-rate-limit', rateLimitInfo);
- }
- }
-
- // Emit final progress
- const finalPhase = code === 0 ? 'complete' : 'failed';
- this.emit('execution-progress', taskId, {
- phase: finalPhase,
- phaseProgress: 100,
- overallProgress: code === 0 ? 100 : this.calculateOverallProgress(currentPhase, phaseProgress),
- message: code === 0 ? 'Process completed successfully' : `Process exited with code ${code}`
- });
-
- this.emit('exit', taskId, code, processType);
- });
-
- // Handle process error
- childProcess.on('error', (err: Error) => {
- console.log('[spawnProcess] Process error:', err.message);
- this.processes.delete(taskId);
-
- this.emit('execution-progress', taskId, {
- phase: 'failed',
- phaseProgress: 0,
- overallProgress: 0,
- message: `Error: ${err.message}`
- });
-
- this.emit('error', taskId, err.message);
- });
- }
-
- /**
- * Kill a specific task's process
- */
- killTask(taskId: string): boolean {
- const agentProcess = this.processes.get(taskId);
- if (agentProcess) {
- try {
- // Mark this specific spawn as killed so its exit handler knows to ignore
- this.killedSpawnIds.add(agentProcess.spawnId);
-
- // Send SIGTERM first for graceful shutdown
- agentProcess.process.kill('SIGTERM');
-
- // Force kill after timeout
- setTimeout(() => {
- if (!agentProcess.process.killed) {
- agentProcess.process.kill('SIGKILL');
- }
- }, 5000);
-
- this.processes.delete(taskId);
- return true;
- } catch {
- return false;
- }
- }
- return false;
- }
-
- /**
- * Stop ideation generation for a project
- */
- stopIdeation(projectId: string): boolean {
- const wasRunning = this.isRunning(projectId);
- if (wasRunning) {
- this.killTask(projectId);
- this.emit('ideation-stopped', projectId);
- return true;
- }
- return false;
- }
-
- /**
- * Check if ideation is running for a project
- */
- isIdeationRunning(projectId: string): boolean {
- return this.isRunning(projectId);
- }
-
- /**
- * Kill all running processes
- */
- async killAll(): Promise {
- const killPromises = Array.from(this.processes.keys()).map((taskId) => {
- return new Promise((resolve) => {
- this.killTask(taskId);
- resolve();
- });
- });
- await Promise.all(killPromises);
- }
-
- /**
- * Check if a task is running
- */
- isRunning(taskId: string): boolean {
- return this.processes.has(taskId);
- }
-
- /**
- * Get all running task IDs
- */
- getRunningTasks(): string[] {
- return Array.from(this.processes.keys());
- }
-}
diff --git a/auto-claude-ui/src/main/ipc-handlers.ts.backup b/auto-claude-ui/src/main/ipc-handlers.ts.backup
deleted file mode 100644
index 2773f823..00000000
--- a/auto-claude-ui/src/main/ipc-handlers.ts.backup
+++ /dev/null
@@ -1,6913 +0,0 @@
-import { ipcMain, dialog, BrowserWindow, app } from 'electron';
-import path from 'path';
-import { existsSync, readFileSync, writeFileSync, readdirSync, statSync, mkdirSync } from 'fs';
-import { spawn, execSync } from 'child_process';
-import { IPC_CHANNELS, DEFAULT_APP_SETTINGS, AUTO_BUILD_PATHS, getSpecsDir } from '../shared/constants';
-import type {
- Project,
- ProjectSettings,
- Task,
- TaskMetadata,
- TaskCategory,
- TaskComplexity,
- TaskImpact,
- TaskStatus,
- AppSettings,
- IPCResult,
- TaskStartOptions,
- ImplementationPlan,
- TerminalCreateOptions,
- AutoBuildVersionInfo,
- InitializationResult,
- Roadmap,
- RoadmapFeature,
- RoadmapFeatureStatus,
- RoadmapGenerationStatus,
- ProjectIndex,
- ProjectContextData,
- GraphitiMemoryStatus,
- GraphitiMemoryState,
- MemoryEpisode,
- ContextSearchResult,
- ProjectEnvConfig,
- ClaudeAuthResult,
- LinearIssue,
- LinearTeam,
- LinearProject,
- LinearImportResult,
- LinearSyncStatus,
- GitHubRepository,
- GitHubIssue,
- GitHubSyncStatus,
- GitHubImportResult,
- GitHubInvestigationResult,
- GitHubInvestigationStatus,
- IdeationSession,
- IdeationConfig,
- IdeationGenerationStatus,
- IdeationStatus,
- SourceEnvConfig,
- SourceEnvCheckResult,
- ClaudeProfile,
- ClaudeProfileSettings
-} from '../shared/types';
-import { projectStore } from './project-store';
-import { fileWatcher } from './file-watcher';
-import { AgentManager } from './agent';
-import { TerminalManager } from './terminal-manager';
-import { getClaudeProfileManager } from './claude-profile-manager';
-import {
- initializeProject,
- isInitialized,
- getAutoBuildPath,
- hasLocalSource
-} from './project-initializer';
-import {
- checkForUpdates as checkSourceUpdates,
- downloadAndApplyUpdate,
- getBundledVersion,
- getEffectiveSourcePath
-} from './auto-claude-updater';
-import { changelogService } from './changelog-service';
-import { insightsService } from './insights-service';
-import { taskLogService } from './task-log-service';
-import { titleGenerator } from './title-generator';
-import { PythonEnvManager, PythonEnvStatus } from './python-env-manager';
-import type { AutoBuildSourceUpdateProgress, InsightsSession, InsightsSessionSummary, InsightsChatStatus, InsightsStreamChunk, TaskLogs, TaskLogStreamChunk, FileNode } from '../shared/types';
-
-/**
- * Setup all IPC handlers
- */
-export function setupIpcHandlers(
- agentManager: AgentManager,
- terminalManager: TerminalManager,
- getMainWindow: () => BrowserWindow | null,
- pythonEnvManager: PythonEnvManager
-): void {
- // ============================================
- // Project Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.PROJECT_ADD,
- async (_, projectPath: string): Promise> => {
- try {
- // Validate path exists
- if (!existsSync(projectPath)) {
- return { success: false, error: 'Directory does not exist' };
- }
-
- const project = projectStore.addProject(projectPath);
- return { success: true, data: project };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Unknown error'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.PROJECT_REMOVE,
- async (_, projectId: string): Promise => {
- const success = projectStore.removeProject(projectId);
- return { success };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.PROJECT_LIST,
- async (): Promise> => {
- // Validate that .auto-claude folders still exist for all projects
- // If a folder was deleted, reset autoBuildPath so UI prompts for reinitialization
- const resetIds = projectStore.validateProjects();
- if (resetIds.length > 0) {
- console.log('[IPC] PROJECT_LIST: Detected missing .auto-claude folders for', resetIds.length, 'project(s)');
- }
-
- const projects = projectStore.getProjects();
- console.log('[IPC] PROJECT_LIST returning', projects.length, 'projects');
- return { success: true, data: projects };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.PROJECT_UPDATE_SETTINGS,
- async (
- _,
- projectId: string,
- settings: Partial
- ): Promise => {
- const project = projectStore.updateProjectSettings(projectId, settings);
- if (project) {
- return { success: true };
- }
- return { success: false, error: 'Project not found' };
- }
- );
-
- // ============================================
- // Project Initialization Operations
- // ============================================
-
- const settingsPath = path.join(app.getPath('userData'), 'settings.json');
-
- /**
- * Auto-detect the auto-claude source path relative to the app location
- * In dev: auto-claude-ui/../auto-claude
- * In prod: Could be bundled or configured
- */
- const detectAutoBuildSourcePath = (): string | null => {
- // Try relative to app directory (works in dev and if repo structure is maintained)
- // __dirname in main process points to out/main in dev
- const possiblePaths = [
- // Dev mode: from out/main -> ../../../auto-claude (sibling to auto-claude-ui)
- path.resolve(__dirname, '..', '..', '..', 'auto-claude'),
- // Alternative: from app root (useful in some packaged scenarios)
- path.resolve(app.getAppPath(), '..', 'auto-claude'),
- // If running from repo root
- path.resolve(process.cwd(), 'auto-claude'),
- // Try one more level up (in case of different build output structure)
- path.resolve(__dirname, '..', '..', 'auto-claude')
- ];
-
- for (const p of possiblePaths) {
- if (existsSync(p) && existsSync(path.join(p, 'VERSION'))) {
- return p;
- }
- }
- return null;
- };
-
- /**
- * Get the configured auto-claude source path from settings, or auto-detect
- */
- const getAutoBuildSourcePath = (): string | null => {
- // First check if manually configured
- if (existsSync(settingsPath)) {
- try {
- const content = readFileSync(settingsPath, 'utf-8');
- const settings = JSON.parse(content);
- if (settings.autoBuildPath && existsSync(settings.autoBuildPath)) {
- return settings.autoBuildPath;
- }
- } catch {
- // Fall through to auto-detect
- }
- }
-
- // Auto-detect from app location
- return detectAutoBuildSourcePath();
- };
-
- /**
- * Configure all Python-dependent services with the managed Python path
- */
- const configureServicesWithPython = (pythonPath: string, autoBuildPath: string): void => {
- console.log('[IPC] Configuring services with Python:', pythonPath);
- agentManager.configure(pythonPath, autoBuildPath);
- changelogService.configure(pythonPath, autoBuildPath);
- insightsService.configure(pythonPath, autoBuildPath);
- titleGenerator.configure(pythonPath, autoBuildPath);
- };
-
- /**
- * Initialize the Python environment and configure services
- */
- const initializePythonEnvironment = async (): Promise => {
- const autoBuildSource = getAutoBuildSourcePath();
- if (!autoBuildSource) {
- console.log('[IPC] Auto-build source not found, skipping Python env init');
- return {
- ready: false,
- pythonPath: null,
- venvExists: false,
- depsInstalled: false,
- error: 'Auto-build source not found'
- };
- }
-
- console.log('[IPC] Initializing Python environment...');
- const status = await pythonEnvManager.initialize(autoBuildSource);
-
- if (status.ready && status.pythonPath) {
- configureServicesWithPython(status.pythonPath, autoBuildSource);
- }
-
- return status;
- };
-
- // Set up Python environment status events
- pythonEnvManager.on('status', (message: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send('python-env:status', message);
- }
- });
-
- pythonEnvManager.on('error', (error: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send('python-env:error', error);
- }
- });
-
- pythonEnvManager.on('ready', (pythonPath: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send('python-env:ready', pythonPath);
- }
- });
-
- // Initialize Python environment on startup (non-blocking)
- initializePythonEnvironment().then((status) => {
- console.log('[IPC] Python environment initialized:', status);
- });
-
- // IPC handler to get Python environment status
- ipcMain.handle(
- 'python-env:get-status',
- async (): Promise> => {
- const status = await pythonEnvManager.getStatus();
- return { success: true, data: status };
- }
- );
-
- // IPC handler to reinitialize Python environment
- ipcMain.handle(
- 'python-env:reinitialize',
- async (): Promise> => {
- const status = await initializePythonEnvironment();
- return { success: status.ready, data: status, error: status.error };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.PROJECT_INITIALIZE,
- async (_, projectId: string): Promise> => {
- try {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const result = initializeProject(project.path);
-
- if (result.success) {
- // Update project's autoBuildPath
- projectStore.updateAutoBuildPath(projectId, '.auto-claude');
- }
-
- return { success: result.success, data: result, error: result.error };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Unknown error'
- };
- }
- }
- );
-
- // PROJECT_UPDATE_AUTOBUILD is deprecated - .auto-claude only contains data, no code to update
- // Kept for API compatibility, returns success immediately
- ipcMain.handle(
- IPC_CHANNELS.PROJECT_UPDATE_AUTOBUILD,
- async (_, projectId: string): Promise> => {
- try {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- // Nothing to update - .auto-claude only contains data directories
- // The framework runs from the source repo
- return { success: true, data: { success: true } };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Unknown error'
- };
- }
- }
- );
-
- // PROJECT_CHECK_VERSION now just checks if project is initialized
- // Version tracking for .auto-claude is removed since it only contains data
- ipcMain.handle(
- IPC_CHANNELS.PROJECT_CHECK_VERSION,
- async (_, projectId: string): Promise> => {
- try {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- return {
- success: true,
- data: {
- isInitialized: isInitialized(project.path),
- updateAvailable: false // No updates for .auto-claude - it's just data
- }
- };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Unknown error'
- };
- }
- }
- );
-
- // Check if project has local auto-claude source (is dev project)
- ipcMain.handle(
- 'project:has-local-source',
- async (_, projectId: string): Promise> => {
- try {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
- return { success: true, data: hasLocalSource(project.path) };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Unknown error'
- };
- }
- }
- );
-
- // ============================================
- // Task Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_LIST,
- async (_, projectId: string): Promise> => {
- console.log('[IPC] TASK_LIST called with projectId:', projectId);
- const tasks = projectStore.getTasks(projectId);
- console.log('[IPC] TASK_LIST returning', tasks.length, 'tasks');
- return { success: true, data: tasks };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_CREATE,
- async (
- _,
- projectId: string,
- title: string,
- description: string,
- metadata?: TaskMetadata
- ): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- // Auto-generate title if empty using Claude AI
- let finalTitle = title;
- if (!title || !title.trim()) {
- console.log('[TASK_CREATE] Title is empty, generating with Claude AI...');
- try {
- const generatedTitle = await titleGenerator.generateTitle(description);
- if (generatedTitle) {
- finalTitle = generatedTitle;
- console.log('[TASK_CREATE] Generated title:', finalTitle);
- } else {
- // Fallback: create title from first line of description
- finalTitle = description.split('\n')[0].substring(0, 60);
- if (finalTitle.length === 60) finalTitle += '...';
- console.log('[TASK_CREATE] AI generation failed, using fallback:', finalTitle);
- }
- } catch (err) {
- console.error('[TASK_CREATE] Title generation error:', err);
- // Fallback: create title from first line of description
- finalTitle = description.split('\n')[0].substring(0, 60);
- if (finalTitle.length === 60) finalTitle += '...';
- }
- }
-
- // Generate a unique spec ID based on existing specs
- // Get specs directory path
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specsDir = path.join(project.path, specsBaseDir);
-
- // Find next available spec number
- let specNumber = 1;
- if (existsSync(specsDir)) {
- const existingDirs = readdirSync(specsDir, { withFileTypes: true })
- .filter(d => d.isDirectory())
- .map(d => d.name);
-
- // Extract numbers from spec directory names (e.g., "001-feature" -> 1)
- const existingNumbers = existingDirs
- .map(name => {
- const match = name.match(/^(\d+)/);
- return match ? parseInt(match[1], 10) : 0;
- })
- .filter(n => n > 0);
-
- if (existingNumbers.length > 0) {
- specNumber = Math.max(...existingNumbers) + 1;
- }
- }
-
- // Create spec ID with zero-padded number and slugified title
- const slugifiedTitle = finalTitle
- .toLowerCase()
- .replace(/[^a-z0-9]+/g, '-')
- .replace(/^-|-$/g, '')
- .substring(0, 50);
- const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`;
-
- // Create spec directory
- const specDir = path.join(specsDir, specId);
- mkdirSync(specDir, { recursive: true });
-
- // Build metadata with source type
- const taskMetadata: TaskMetadata = {
- sourceType: 'manual',
- ...metadata
- };
-
- // Process and save attached images
- if (taskMetadata.attachedImages && taskMetadata.attachedImages.length > 0) {
- const attachmentsDir = path.join(specDir, 'attachments');
- mkdirSync(attachmentsDir, { recursive: true });
-
- const savedImages: typeof taskMetadata.attachedImages = [];
-
- for (const image of taskMetadata.attachedImages) {
- if (image.data) {
- try {
- // Decode base64 and save to file
- const buffer = Buffer.from(image.data, 'base64');
- const imagePath = path.join(attachmentsDir, image.filename);
- writeFileSync(imagePath, buffer);
-
- // Store relative path instead of base64 data
- savedImages.push({
- id: image.id,
- filename: image.filename,
- mimeType: image.mimeType,
- size: image.size,
- path: `attachments/${image.filename}`
- // Don't include data or thumbnail to save space
- });
- } catch (err) {
- console.error(`Failed to save image ${image.filename}:`, err);
- }
- }
- }
-
- // Update metadata with saved image paths (without base64 data)
- taskMetadata.attachedImages = savedImages;
- }
-
- // Create initial implementation_plan.json (task is created but not started)
- const now = new Date().toISOString();
- const implementationPlan = {
- feature: finalTitle,
- description: description,
- created_at: now,
- updated_at: now,
- status: 'pending',
- phases: []
- };
-
- const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN);
- writeFileSync(planPath, JSON.stringify(implementationPlan, null, 2));
-
- // Save task metadata if provided
- if (taskMetadata) {
- const metadataPath = path.join(specDir, 'task_metadata.json');
- writeFileSync(metadataPath, JSON.stringify(taskMetadata, null, 2));
- }
-
- // Create requirements.json with attached images
- const requirements: Record = {
- task_description: description,
- workflow_type: taskMetadata.category || 'feature'
- };
-
- // Add attached images to requirements if present
- if (taskMetadata.attachedImages && taskMetadata.attachedImages.length > 0) {
- requirements.attached_images = taskMetadata.attachedImages.map(img => ({
- filename: img.filename,
- path: img.path,
- description: '' // User can add descriptions later
- }));
- }
-
- const requirementsPath = path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS);
- writeFileSync(requirementsPath, JSON.stringify(requirements, null, 2));
-
- // Create the task object
- const task: Task = {
- id: specId,
- specId: specId,
- projectId,
- title: finalTitle,
- description,
- status: 'backlog',
- subtasks: [],
- logs: [],
- metadata: taskMetadata,
- createdAt: new Date(),
- updatedAt: new Date()
- };
-
- return { success: true, data: task };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_DELETE,
- async (_, taskId: string): Promise => {
- const { rm } = await import('fs/promises');
-
- // Find task and project
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (!task || !project) {
- return { success: false, error: 'Task or project not found' };
- }
-
- // Check if task is currently running
- const isRunning = agentManager.isRunning(taskId);
- if (isRunning) {
- return { success: false, error: 'Cannot delete a running task. Stop the task first.' };
- }
-
- // Delete the spec directory
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(project.path, specsBaseDir, task.specId);
-
- try {
- if (existsSync(specDir)) {
- await rm(specDir, { recursive: true, force: true });
- console.log(`[TASK_DELETE] Deleted spec directory: ${specDir}`);
- }
- return { success: true };
- } catch (error) {
- console.error('[TASK_DELETE] Error deleting spec directory:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to delete task files'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_UPDATE,
- async (
- _,
- taskId: string,
- updates: { title?: string; description?: string }
- ): Promise> => {
- try {
- // Find task and project
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- const autoBuildDir = project.autoBuildPath || '.auto-claude';
- const specDir = path.join(project.path, autoBuildDir, 'specs', task.specId);
-
- if (!existsSync(specDir)) {
- return { success: false, error: 'Spec directory not found' };
- }
-
- // Auto-generate title if empty
- let finalTitle = updates.title;
- if (updates.title !== undefined && !updates.title.trim()) {
- // Get description to use for title generation
- const descriptionToUse = updates.description ?? task.description;
- console.log('[TASK_UPDATE] Title is empty, generating with Claude AI...');
- try {
- const generatedTitle = await titleGenerator.generateTitle(descriptionToUse);
- if (generatedTitle) {
- finalTitle = generatedTitle;
- console.log('[TASK_UPDATE] Generated title:', finalTitle);
- } else {
- // Fallback: create title from first line of description
- finalTitle = descriptionToUse.split('\n')[0].substring(0, 60);
- if (finalTitle.length === 60) finalTitle += '...';
- console.log('[TASK_UPDATE] AI generation failed, using fallback:', finalTitle);
- }
- } catch (err) {
- console.error('[TASK_UPDATE] Title generation error:', err);
- // Fallback: create title from first line of description
- finalTitle = descriptionToUse.split('\n')[0].substring(0, 60);
- if (finalTitle.length === 60) finalTitle += '...';
- }
- }
-
- // Update implementation_plan.json
- const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN);
- if (existsSync(planPath)) {
- try {
- const planContent = readFileSync(planPath, 'utf-8');
- const plan = JSON.parse(planContent);
-
- if (finalTitle !== undefined) {
- plan.feature = finalTitle;
- }
- if (updates.description !== undefined) {
- plan.description = updates.description;
- }
- plan.updated_at = new Date().toISOString();
-
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- } catch {
- // Plan file might not be valid JSON, continue anyway
- }
- }
-
- // Update spec.md if it exists
- const specPath = path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE);
- if (existsSync(specPath)) {
- try {
- let specContent = readFileSync(specPath, 'utf-8');
-
- // Update title (first # heading)
- if (finalTitle !== undefined) {
- specContent = specContent.replace(
- /^#\s+.*$/m,
- `# ${finalTitle}`
- );
- }
-
- // Update description (## Overview section content)
- if (updates.description !== undefined) {
- // Replace content between ## Overview and the next ## section
- specContent = specContent.replace(
- /(## Overview\n)([\s\S]*?)((?=\n## )|$)/,
- `$1${updates.description}\n\n$3`
- );
- }
-
- writeFileSync(specPath, specContent);
- } catch {
- // Spec file update failed, continue anyway
- }
- }
-
- // Build the updated task object
- const updatedTask: Task = {
- ...task,
- title: finalTitle ?? task.title,
- description: updates.description ?? task.description,
- updatedAt: new Date()
- };
-
- return { success: true, data: updatedTask };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Unknown error'
- };
- }
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.TASK_START,
- (_, taskId: string, options?: TaskStartOptions) => {
- console.log('[TASK_START] Received request for taskId:', taskId);
- const mainWindow = getMainWindow();
- if (!mainWindow) {
- console.log('[TASK_START] No main window found');
- return;
- }
-
- // Find task and project
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (!task || !project) {
- console.log('[TASK_START] Task or project not found for taskId:', taskId);
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_ERROR,
- taskId,
- 'Task or project not found'
- );
- return;
- }
-
- console.log('[TASK_START] Found task:', task.specId, 'status:', task.status, 'subtasks:', task.subtasks.length);
-
- // Start file watcher for this task
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(
- project.path,
- specsBaseDir,
- task.specId
- );
- fileWatcher.watch(taskId, specDir);
-
- // Check if spec.md exists (indicates spec creation was already done or in progress)
- const specFilePath = path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE);
- const hasSpec = existsSync(specFilePath);
-
- // Check if this task needs spec creation first (no spec file = not yet created)
- // OR if it has a spec but no implementation plan subtasks (spec created, needs planning/building)
- const needsSpecCreation = !hasSpec;
- const needsImplementation = hasSpec && task.subtasks.length === 0;
-
- console.log('[TASK_START] hasSpec:', hasSpec, 'needsSpecCreation:', needsSpecCreation, 'needsImplementation:', needsImplementation);
-
- if (needsSpecCreation) {
- // No spec file - need to run spec_runner.py to create the spec
- const taskDescription = task.description || task.title;
- console.log('[TASK_START] Starting spec creation for:', task.specId, 'in:', specDir);
-
- // Start spec creation process - pass the existing spec directory
- // so spec_runner uses it instead of creating a new one
- agentManager.startSpecCreation(task.specId, project.path, taskDescription, specDir, task.metadata);
- } else if (needsImplementation) {
- // Spec exists but no subtasks - run run.py to create implementation plan and execute
- // Read the spec.md to get the task description
- let taskDescription = task.description || task.title;
- try {
- taskDescription = readFileSync(specFilePath, 'utf-8');
- } catch {
- // Use default description
- }
-
- console.log('[TASK_START] Starting task execution (no subtasks) for:', task.specId);
- // Start task execution which will create the implementation plan
- // Note: No parallel mode for planning phase - parallel only makes sense with multiple subtasks
- agentManager.startTaskExecution(
- taskId,
- project.path,
- task.specId,
- {
- parallel: false, // Sequential for planning phase
- workers: 1
- }
- );
- } else {
- // Task has subtasks, start normal execution
- // Only enable parallel if there are multiple subtasks AND user has parallel enabled
- const hasMultipleSubtasks = task.subtasks.length > 1;
- const pendingSubtasks = task.subtasks.filter(s => s.status === 'pending' || s.status === 'in_progress').length;
- const parallelEnabled = options?.parallel ?? project.settings.parallelEnabled;
- const useParallel = parallelEnabled && hasMultipleSubtasks && pendingSubtasks > 1;
- const workers = useParallel ? (options?.workers ?? project.settings.maxWorkers) : 1;
-
- console.log('[TASK_START] Starting task execution (has subtasks) for:', task.specId);
- console.log('[TASK_START] Parallel decision:', {
- hasMultipleSubtasks,
- pendingSubtasks,
- parallelEnabled,
- useParallel,
- workers
- });
-
- agentManager.startTaskExecution(
- taskId,
- project.path,
- task.specId,
- {
- parallel: useParallel,
- workers
- }
- );
- }
-
- // Notify status change
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- 'in_progress'
- );
- }
- );
-
- ipcMain.on(IPC_CHANNELS.TASK_STOP, (_, taskId: string) => {
- agentManager.killTask(taskId);
- fileWatcher.unwatch(taskId);
-
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- 'backlog'
- );
- }
- });
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_REVIEW,
- async (
- _,
- taskId: string,
- approved: boolean,
- feedback?: string
- ): Promise => {
- // Find task and project
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Check if dev mode is enabled for this project
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(
- project.path,
- specsBaseDir,
- task.specId
- );
-
- if (approved) {
- // Write approval to QA report
- const qaReportPath = path.join(specDir, AUTO_BUILD_PATHS.QA_REPORT);
- writeFileSync(
- qaReportPath,
- `# QA Review\n\nStatus: APPROVED\n\nReviewed at: ${new Date().toISOString()}\n`
- );
-
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- 'done'
- );
- }
- } else {
- // Write feedback for QA fixer
- const fixRequestPath = path.join(specDir, 'QA_FIX_REQUEST.md');
- writeFileSync(
- fixRequestPath,
- `# QA Fix Request\n\nStatus: REJECTED\n\n## Feedback\n\n${feedback || 'No feedback provided'}\n\nCreated at: ${new Date().toISOString()}\n`
- );
-
- // Restart QA process with dev mode
- agentManager.startQAProcess(taskId, project.path, task.specId);
-
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- 'in_progress'
- );
- }
- }
-
- return { success: true };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_UPDATE_STATUS,
- async (
- _,
- taskId: string,
- status: TaskStatus
- ): Promise => {
- // Find task and project
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Get the spec directory
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(
- project.path,
- specsBaseDir,
- task.specId
- );
-
- // Update implementation_plan.json if it exists
- const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN);
-
- try {
- if (existsSync(planPath)) {
- const planContent = readFileSync(planPath, 'utf-8');
- const plan = JSON.parse(planContent);
-
- // Store the exact UI status - project-store.ts will map it back
- plan.status = status;
- // Also store mapped version for Python compatibility
- plan.planStatus = status === 'done' ? 'completed'
- : status === 'in_progress' ? 'in_progress'
- : status === 'ai_review' ? 'review'
- : status === 'human_review' ? 'review'
- : 'pending';
- plan.updated_at = new Date().toISOString();
-
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- } else {
- // If no implementation plan exists yet, create a basic one
- const plan = {
- feature: task.title,
- description: task.description || '',
- created_at: task.createdAt.toISOString(),
- updated_at: new Date().toISOString(),
- status: status, // Store exact UI status for persistence
- planStatus: status === 'done' ? 'completed'
- : status === 'in_progress' ? 'in_progress'
- : status === 'ai_review' ? 'review'
- : status === 'human_review' ? 'review'
- : 'pending',
- phases: []
- };
-
- // Ensure spec directory exists
- if (!existsSync(specDir)) {
- mkdirSync(specDir, { recursive: true });
- }
-
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- }
-
- // Auto-start task when status changes to 'in_progress' and no process is running
- if (status === 'in_progress' && !agentManager.isRunning(taskId)) {
- const mainWindow = getMainWindow();
- console.log('[TASK_UPDATE_STATUS] Auto-starting task:', taskId);
-
- // Start file watcher for this task
- fileWatcher.watch(taskId, specDir);
-
- // Check if spec.md exists
- const specFilePath = path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE);
- const hasSpec = existsSync(specFilePath);
- const needsSpecCreation = !hasSpec;
- const needsImplementation = hasSpec && task.subtasks.length === 0;
-
- console.log('[TASK_UPDATE_STATUS] hasSpec:', hasSpec, 'needsSpecCreation:', needsSpecCreation, 'needsImplementation:', needsImplementation);
-
- if (needsSpecCreation) {
- // No spec file - need to run spec_runner.py to create the spec
- const taskDescription = task.description || task.title;
- console.log('[TASK_UPDATE_STATUS] Starting spec creation for:', task.specId);
- agentManager.startSpecCreation(task.specId, project.path, taskDescription, specDir, task.metadata);
- } else if (needsImplementation) {
- // Spec exists but no subtasks - run run.py to create implementation plan and execute
- console.log('[TASK_UPDATE_STATUS] Starting task execution (no subtasks) for:', task.specId);
- agentManager.startTaskExecution(
- taskId,
- project.path,
- task.specId,
- {
- parallel: false,
- workers: 1
- }
- );
- } else {
- // Task has subtasks, start normal execution
- const hasMultipleSubtasks = task.subtasks.length > 1;
- const pendingSubtasks = task.subtasks.filter(s => s.status === 'pending' || s.status === 'in_progress').length;
- const parallelEnabled = project.settings.parallelEnabled;
- const useParallel = parallelEnabled && hasMultipleSubtasks && pendingSubtasks > 1;
- const workers = useParallel ? project.settings.maxWorkers : 1;
-
- console.log('[TASK_UPDATE_STATUS] Starting task execution (has subtasks) for:', task.specId);
- agentManager.startTaskExecution(
- taskId,
- project.path,
- task.specId,
- {
- parallel: useParallel,
- workers
- }
- );
- }
-
- // Notify renderer about status change
- if (mainWindow) {
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- 'in_progress'
- );
- }
- }
-
- return { success: true };
- } catch (error) {
- console.error('Failed to update task status:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to update task status'
- };
- }
- }
- );
-
- // Handler to check if a task is actually running (has active process)
- ipcMain.handle(
- IPC_CHANNELS.TASK_CHECK_RUNNING,
- async (_, taskId: string): Promise> => {
- const isRunning = agentManager.isRunning(taskId);
- return { success: true, data: isRunning };
- }
- );
-
- // Handler to recover a stuck task (status says in_progress but no process running)
- ipcMain.handle(
- IPC_CHANNELS.TASK_RECOVER_STUCK,
- async (
- _,
- taskId: string,
- options?: { targetStatus?: TaskStatus; autoRestart?: boolean }
- ): Promise> => {
- const targetStatus = options?.targetStatus;
- const autoRestart = options?.autoRestart ?? false;
- // Check if task is actually running
- const isActuallyRunning = agentManager.isRunning(taskId);
-
- if (isActuallyRunning) {
- return {
- success: false,
- error: 'Task is still running. Stop it first before recovering.',
- data: {
- taskId,
- recovered: false,
- newStatus: 'in_progress' as TaskStatus,
- message: 'Task is still running'
- }
- };
- }
-
- // Find task and project
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Get the spec directory
- const autoBuildDir = project.autoBuildPath || '.auto-claude';
- const specDir = path.join(
- project.path,
- autoBuildDir,
- 'specs',
- task.specId
- );
-
- // Update implementation_plan.json
- const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN);
-
- try {
- // Read the plan to analyze subtask progress
- let plan: Record | null = null;
- if (existsSync(planPath)) {
- const planContent = readFileSync(planPath, 'utf-8');
- plan = JSON.parse(planContent);
- }
-
- // Determine the target status intelligently based on subtask progress
- // If targetStatus is explicitly provided, use it; otherwise calculate from subtasks
- let newStatus: TaskStatus = targetStatus || 'backlog';
-
- if (!targetStatus && plan?.phases && Array.isArray(plan.phases)) {
- // Analyze subtask statuses to determine appropriate recovery status
- const allSubtasks: Array<{ status: string }> = [];
- for (const phase of plan.phases as Array<{ subtasks?: Array<{ status: string }> }>) {
- if (phase.subtasks && Array.isArray(phase.subtasks)) {
- allSubtasks.push(...phase.subtasks);
- }
- }
-
- if (allSubtasks.length > 0) {
- const completedCount = allSubtasks.filter(s => s.status === 'completed').length;
- const allCompleted = completedCount === allSubtasks.length;
-
- if (allCompleted) {
- // All subtasks completed - should go to review (ai_review or human_review based on source)
- // For recovery, human_review is safer as it requires manual verification
- newStatus = 'human_review';
- } else if (completedCount > 0) {
- // Some subtasks completed, some still pending - task is in progress
- newStatus = 'in_progress';
- }
- // else: no subtasks completed, stay with 'backlog'
- }
- }
-
- if (plan) {
- // Update status
- plan.status = newStatus;
- plan.planStatus = newStatus === 'done' ? 'completed'
- : newStatus === 'in_progress' ? 'in_progress'
- : newStatus === 'ai_review' ? 'review'
- : newStatus === 'human_review' ? 'review'
- : 'pending';
- plan.updated_at = new Date().toISOString();
-
- // Add recovery note
- plan.recoveryNote = `Task recovered from stuck state at ${new Date().toISOString()}`;
-
- // Reset in_progress and failed subtask statuses to 'pending' so they can be retried
- // Keep completed subtasks as-is so run.py can resume from where it left off
- if (plan.phases && Array.isArray(plan.phases)) {
- for (const phase of plan.phases as Array<{ subtasks?: Array<{ status: string; actual_output?: string; started_at?: string; completed_at?: string }> }>) {
- if (phase.subtasks && Array.isArray(phase.subtasks)) {
- for (const subtask of phase.subtasks) {
- // Reset in_progress subtasks to pending (they were interrupted)
- // Keep completed subtasks as-is so run.py can resume
- if (subtask.status === 'in_progress') {
- subtask.status = 'pending';
- // Clear execution data to maintain consistency
- delete subtask.actual_output;
- delete subtask.started_at;
- delete subtask.completed_at;
- }
- // Also reset failed subtasks so they can be retried
- if (subtask.status === 'failed') {
- subtask.status = 'pending';
- // Clear execution data to maintain consistency
- delete subtask.actual_output;
- delete subtask.started_at;
- delete subtask.completed_at;
- }
- }
- }
- }
- }
-
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- }
-
- // Stop file watcher if it was watching this task
- fileWatcher.unwatch(taskId);
-
- // Auto-restart the task if requested
- let autoRestarted = false;
- if (autoRestart && project) {
- try {
- // Set status to in_progress for the restart
- newStatus = 'in_progress';
-
- // Update plan status for restart
- if (plan) {
- plan.status = 'in_progress';
- plan.planStatus = 'in_progress';
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- }
-
- // Start the task execution
-
- // Check if we should use parallel mode
- const hasMultipleSubtasks = task.subtasks.length > 1;
- const pendingSubtasks = task.subtasks.filter(s => s.status === 'pending').length;
- const parallelEnabled = project.settings.parallelEnabled;
- const useParallel = parallelEnabled && hasMultipleSubtasks && pendingSubtasks > 1;
- const workers = useParallel ? project.settings.maxWorkers : 1;
-
- // Start file watcher for this task
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specDirForWatcher = path.join(project.path, specsBaseDir, task.specId);
- fileWatcher.watch(taskId, specDirForWatcher);
-
- agentManager.startTaskExecution(
- taskId,
- project.path,
- task.specId,
- {
- parallel: useParallel,
- workers
- }
- );
-
- autoRestarted = true;
- console.log(`[Recovery] Auto-restarted task ${taskId}`);
- } catch (restartError) {
- console.error('Failed to auto-restart task after recovery:', restartError);
- // Recovery succeeded but restart failed - still report success
- }
- }
-
- // Notify renderer of status change
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- newStatus
- );
- }
-
- return {
- success: true,
- data: {
- taskId,
- recovered: true,
- newStatus,
- message: autoRestarted
- ? 'Task recovered and restarted successfully'
- : `Task recovered successfully and moved to ${newStatus}`,
- autoRestarted
- }
- };
- } catch (error) {
- console.error('Failed to recover stuck task:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to recover task'
- };
- }
- }
- );
-
- // ============================================
- // Workspace Management Operations (for human review)
- // ============================================
-
- /**
- * Helper function to find task and project by taskId
- */
- const findTaskAndProject = (taskId: string): { task: Task | undefined; project: Project | undefined } => {
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- return { task, project };
- };
-
- /**
- * Get the worktree status for a task
- * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_WORKTREE_STATUS,
- async (_, taskId: string): Promise> => {
- try {
- const { task, project } = findTaskAndProject(taskId);
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Per-spec worktree path: .worktrees/{spec-name}/
- const worktreePath = path.join(project.path, '.worktrees', task.specId);
-
- if (!existsSync(worktreePath)) {
- return {
- success: true,
- data: { exists: false }
- };
- }
-
- // Get branch info from git
- try {
- // Get current branch in worktree
- const branch = execSync('git rev-parse --abbrev-ref HEAD', {
- cwd: worktreePath,
- encoding: 'utf-8'
- }).trim();
-
- // Get base branch (usually main or master)
- let baseBranch = 'main';
- try {
- // Try to get the default branch
- baseBranch = execSync('git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo main', {
- cwd: project.path,
- encoding: 'utf-8'
- }).trim().replace('origin/', '');
- } catch {
- baseBranch = 'main';
- }
-
- // Get commit count
- let commitCount = 0;
- try {
- const countOutput = execSync(`git rev-list --count ${baseBranch}..HEAD 2>/dev/null || echo 0`, {
- cwd: worktreePath,
- encoding: 'utf-8'
- }).trim();
- commitCount = parseInt(countOutput, 10) || 0;
- } catch {
- commitCount = 0;
- }
-
- // Get diff stats
- let filesChanged = 0;
- let additions = 0;
- let deletions = 0;
-
- try {
- const diffStat = execSync(`git diff --stat ${baseBranch}...HEAD 2>/dev/null || echo ""`, {
- cwd: worktreePath,
- encoding: 'utf-8'
- }).trim();
-
- // Parse the summary line (e.g., "3 files changed, 50 insertions(+), 10 deletions(-)")
- const summaryMatch = diffStat.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/);
- if (summaryMatch) {
- filesChanged = parseInt(summaryMatch[1], 10) || 0;
- additions = parseInt(summaryMatch[2], 10) || 0;
- deletions = parseInt(summaryMatch[3], 10) || 0;
- }
- } catch {
- // Ignore diff errors
- }
-
- return {
- success: true,
- data: {
- exists: true,
- worktreePath,
- branch,
- baseBranch,
- commitCount,
- filesChanged,
- additions,
- deletions
- }
- };
- } catch (gitError) {
- console.error('Git error getting worktree status:', gitError);
- return {
- success: true,
- data: { exists: true, worktreePath }
- };
- }
- } catch (error) {
- console.error('Failed to get worktree status:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get worktree status'
- };
- }
- }
- );
-
- /**
- * Get the diff for a task's worktree
- * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_WORKTREE_DIFF,
- async (_, taskId: string): Promise> => {
- try {
- const { task, project } = findTaskAndProject(taskId);
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Per-spec worktree path: .worktrees/{spec-name}/
- const worktreePath = path.join(project.path, '.worktrees', task.specId);
-
- if (!existsSync(worktreePath)) {
- return { success: false, error: 'No worktree found for this task' };
- }
-
- // Get base branch
- let baseBranch = 'main';
- try {
- baseBranch = execSync('git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo main', {
- cwd: project.path,
- encoding: 'utf-8'
- }).trim().replace('origin/', '');
- } catch {
- baseBranch = 'main';
- }
-
- // Get the diff with file stats
- const files: import('../shared/types').WorktreeDiffFile[] = [];
-
- try {
- // Get numstat for additions/deletions per file
- const numstat = execSync(`git diff --numstat ${baseBranch}...HEAD 2>/dev/null || echo ""`, {
- cwd: worktreePath,
- encoding: 'utf-8'
- }).trim();
-
- // Get name-status for file status
- const nameStatus = execSync(`git diff --name-status ${baseBranch}...HEAD 2>/dev/null || echo ""`, {
- cwd: worktreePath,
- encoding: 'utf-8'
- }).trim();
-
- // Parse name-status to get file statuses
- const statusMap: Record = {};
- nameStatus.split('\n').filter(Boolean).forEach((line: string) => {
- const [status, ...pathParts] = line.split('\t');
- const filePath = pathParts.join('\t'); // Handle files with tabs in name
- switch (status[0]) {
- case 'A': statusMap[filePath] = 'added'; break;
- case 'M': statusMap[filePath] = 'modified'; break;
- case 'D': statusMap[filePath] = 'deleted'; break;
- case 'R': statusMap[pathParts[1] || filePath] = 'renamed'; break;
- default: statusMap[filePath] = 'modified';
- }
- });
-
- // Parse numstat for additions/deletions
- numstat.split('\n').filter(Boolean).forEach((line: string) => {
- const [adds, dels, filePath] = line.split('\t');
- files.push({
- path: filePath,
- status: statusMap[filePath] || 'modified',
- additions: parseInt(adds, 10) || 0,
- deletions: parseInt(dels, 10) || 0
- });
- });
- } catch (diffError) {
- console.error('Error getting diff:', diffError);
- }
-
- // Generate summary
- const totalAdditions = files.reduce((sum, f) => sum + f.additions, 0);
- const totalDeletions = files.reduce((sum, f) => sum + f.deletions, 0);
- const summary = `${files.length} files changed, ${totalAdditions} insertions(+), ${totalDeletions} deletions(-)`;
-
- return {
- success: true,
- data: { files, summary }
- };
- } catch (error) {
- console.error('Failed to get worktree diff:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get worktree diff'
- };
- }
- }
- );
-
- /**
- * Merge the worktree changes into the main branch
- * @param taskId - The task ID to merge
- * @param options - Merge options { noCommit?: boolean }
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_WORKTREE_MERGE,
- async (_, taskId: string, options?: { noCommit?: boolean }): Promise> => {
- try {
- // Ensure Python environment is ready
- if (!pythonEnvManager.isEnvReady()) {
- const autoBuildSource = getEffectiveSourcePath();
- if (autoBuildSource) {
- const status = await pythonEnvManager.initialize(autoBuildSource);
- if (!status.ready) {
- return { success: false, error: `Python environment not ready: ${status.error || 'Unknown error'}` };
- }
- } else {
- return { success: false, error: 'Python environment not ready and Auto Claude source not found' };
- }
- }
-
- const { task, project } = findTaskAndProject(taskId);
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Use run.py --merge to handle the merge
- const sourcePath = getEffectiveSourcePath();
- if (!sourcePath) {
- return { success: false, error: 'Auto Claude source not found' };
- }
-
- const runScript = path.join(sourcePath, 'run.py');
- const specDir = path.join(project.path, project.autoBuildPath || '.auto-claude', 'specs', task.specId);
-
- if (!existsSync(specDir)) {
- return { success: false, error: 'Spec directory not found' };
- }
-
- const args = [
- runScript,
- '--spec', task.specId,
- '--project-dir', project.path,
- '--merge'
- ];
-
- // Add --no-commit flag if requested (stage changes without committing)
- if (options?.noCommit) {
- args.push('--no-commit');
- }
-
- return new Promise((resolve) => {
- const pythonPath = pythonEnvManager.getPythonPath() || 'python3';
- const mergeProcess = spawn(pythonPath, args, {
- cwd: sourcePath,
- env: {
- ...process.env,
- PYTHONUNBUFFERED: '1'
- }
- });
-
- let stdout = '';
- let stderr = '';
-
- mergeProcess.stdout.on('data', (data: Buffer) => {
- stdout += data.toString();
- });
-
- mergeProcess.stderr.on('data', (data: Buffer) => {
- stderr += data.toString();
- });
-
- mergeProcess.on('close', (code: number) => {
- if (code === 0) {
- // Persist the status change to implementation_plan.json
- const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN);
- try {
- if (existsSync(planPath)) {
- const planContent = readFileSync(planPath, 'utf-8');
- const plan = JSON.parse(planContent);
- plan.status = 'done';
- plan.planStatus = 'completed';
- plan.updated_at = new Date().toISOString();
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- }
- } catch (persistError) {
- console.error('Failed to persist task status:', persistError);
- }
-
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_STATUS_CHANGE, taskId, 'done');
- }
-
- resolve({
- success: true,
- data: {
- success: true,
- message: 'Changes merged successfully'
- }
- });
- } else {
- // Check if there were conflicts
- const hasConflicts = stdout.includes('conflict') || stderr.includes('conflict');
-
- resolve({
- success: true,
- data: {
- success: false,
- message: hasConflicts ? 'Merge conflicts detected' : `Merge failed: ${stderr || stdout}`,
- conflictFiles: hasConflicts ? [] : undefined
- }
- });
- }
- });
-
- mergeProcess.on('error', (err: Error) => {
- resolve({
- success: false,
- error: `Failed to run merge: ${err.message}`
- });
- });
- });
- } catch (error) {
- console.error('Failed to merge worktree:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to merge worktree'
- };
- }
- }
- );
-
- /**
- * Discard the worktree changes
- * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_WORKTREE_DISCARD,
- async (_, taskId: string): Promise> => {
- try {
- const { task, project } = findTaskAndProject(taskId);
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Per-spec worktree path: .worktrees/{spec-name}/
- const worktreePath = path.join(project.path, '.worktrees', task.specId);
-
- if (!existsSync(worktreePath)) {
- return {
- success: true,
- data: {
- success: true,
- message: 'No worktree to discard'
- }
- };
- }
-
- try {
- // Get the branch name before removing
- const branch = execSync('git rev-parse --abbrev-ref HEAD', {
- cwd: worktreePath,
- encoding: 'utf-8'
- }).trim();
-
- // Remove the worktree
- execSync(`git worktree remove --force "${worktreePath}"`, {
- cwd: project.path,
- encoding: 'utf-8'
- });
-
- // Delete the branch
- try {
- execSync(`git branch -D "${branch}"`, {
- cwd: project.path,
- encoding: 'utf-8'
- });
- } catch {
- // Branch might already be deleted or not exist
- }
-
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_STATUS_CHANGE, taskId, 'backlog');
- }
-
- return {
- success: true,
- data: {
- success: true,
- message: 'Worktree discarded successfully'
- }
- };
- } catch (gitError) {
- console.error('Git error discarding worktree:', gitError);
- return {
- success: false,
- error: `Failed to discard worktree: ${gitError instanceof Error ? gitError.message : 'Unknown error'}`
- };
- }
- } catch (error) {
- console.error('Failed to discard worktree:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to discard worktree'
- };
- }
- }
- );
-
- /**
- * List all spec worktrees for a project
- * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_LIST_WORKTREES,
- async (_, projectId: string): Promise> => {
- try {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const worktreesDir = path.join(project.path, '.worktrees');
- const worktrees: import('../shared/types').WorktreeListItem[] = [];
-
- if (!existsSync(worktreesDir)) {
- return { success: true, data: { worktrees } };
- }
-
- // Get all directories in .worktrees
- const entries = readdirSync(worktreesDir);
- for (const entry of entries) {
- const entryPath = path.join(worktreesDir, entry);
- const stat = statSync(entryPath);
-
- // Skip worker directories and non-directories
- if (!stat.isDirectory() || entry.startsWith('worker-')) {
- continue;
- }
-
- try {
- // Get branch info
- const branch = execSync('git rev-parse --abbrev-ref HEAD', {
- cwd: entryPath,
- encoding: 'utf-8'
- }).trim();
-
- // Get base branch
- let baseBranch = 'main';
- try {
- baseBranch = execSync('git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo main', {
- cwd: project.path,
- encoding: 'utf-8'
- }).trim().replace('origin/', '');
- } catch {
- baseBranch = 'main';
- }
-
- // Get commit count
- let commitCount = 0;
- try {
- const countOutput = execSync(`git rev-list --count ${baseBranch}..HEAD 2>/dev/null || echo 0`, {
- cwd: entryPath,
- encoding: 'utf-8'
- }).trim();
- commitCount = parseInt(countOutput, 10) || 0;
- } catch {
- commitCount = 0;
- }
-
- // Get diff stats
- let filesChanged = 0;
- let additions = 0;
- let deletions = 0;
-
- try {
- const diffStat = execSync(`git diff --shortstat ${baseBranch}...HEAD 2>/dev/null || echo ""`, {
- cwd: entryPath,
- encoding: 'utf-8'
- }).trim();
-
- const filesMatch = diffStat.match(/(\d+) files? changed/);
- const addMatch = diffStat.match(/(\d+) insertions?/);
- const delMatch = diffStat.match(/(\d+) deletions?/);
-
- if (filesMatch) filesChanged = parseInt(filesMatch[1], 10) || 0;
- if (addMatch) additions = parseInt(addMatch[1], 10) || 0;
- if (delMatch) deletions = parseInt(delMatch[1], 10) || 0;
- } catch {
- // Ignore diff errors
- }
-
- worktrees.push({
- specName: entry,
- path: entryPath,
- branch,
- baseBranch,
- commitCount,
- filesChanged,
- additions,
- deletions
- });
- } catch (gitError) {
- console.error(`Error getting info for worktree ${entry}:`, gitError);
- // Skip this worktree if we can't get git info
- }
- }
-
- return { success: true, data: { worktrees } };
- } catch (error) {
- console.error('Failed to list worktrees:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to list worktrees'
- };
- }
- }
- );
-
- // ============================================
- // Task Archive Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_ARCHIVE,
- async (_, projectId: string, taskIds: string[], version?: string): Promise> => {
- try {
- const success = projectStore.archiveTasks(projectId, taskIds, version);
- return { success, data: success };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to archive tasks'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_UNARCHIVE,
- async (_, projectId: string, taskIds: string[]): Promise> => {
- try {
- const success = projectStore.unarchiveTasks(projectId, taskIds);
- return { success, data: success };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to unarchive tasks'
- };
- }
- }
- );
-
- // ============================================
- // Task Phase Logs (collapsible by phase)
- // ============================================
-
- /**
- * Get task logs from spec directory
- * Returns logs organized by phase (planning, coding, validation)
- * Also checks worktree spec directory for coding/validation logs
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_LOGS_GET,
- async (_, projectId: string, specId: string): Promise> => {
- try {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- // Get specs dir relative to project path
- const specsRelPath = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(project.path, specsRelPath, specId);
-
- if (!existsSync(specDir)) {
- return { success: false, error: 'Spec directory not found' };
- }
-
- // Pass project path and specs path so logs can be loaded from worktree too
- const logs = taskLogService.loadLogs(specDir, project.path, specsRelPath, specId);
- return { success: true, data: logs };
- } catch (error) {
- console.error('Failed to get task logs:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get task logs'
- };
- }
- }
- );
-
- /**
- * Start watching a spec for log changes
- * Emits TASK_LOGS_CHANGED and TASK_LOGS_STREAM events
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_LOGS_WATCH,
- async (_, projectId: string, specId: string): Promise => {
- try {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- // Get specs dir relative to project path
- const specsRelPath = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(project.path, specsRelPath, specId);
-
- if (!existsSync(specDir)) {
- return { success: false, error: 'Spec directory not found' };
- }
-
- // Pass project path and specs relative path so the service can also watch
- // the worktree spec directory (where coding/validation logs are written)
- taskLogService.startWatching(specId, specDir, project.path, specsRelPath);
- return { success: true };
- } catch (error) {
- console.error('Failed to start watching task logs:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to start watching'
- };
- }
- }
- );
-
- /**
- * Stop watching a spec for log changes
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_LOGS_UNWATCH,
- async (_, specId: string): Promise => {
- try {
- taskLogService.stopWatching(specId);
- return { success: true };
- } catch (error) {
- console.error('Failed to stop watching task logs:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to stop watching'
- };
- }
- }
- );
-
- // Setup task log service event forwarding to renderer
- taskLogService.on('logs-changed', (specId: string, logs: TaskLogs) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_LOGS_CHANGED, specId, logs);
- }
- });
-
- taskLogService.on('stream-chunk', (specId: string, chunk: TaskLogStreamChunk) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_LOGS_STREAM, specId, chunk);
- }
- });
-
- // ============================================
- // Settings Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.SETTINGS_GET,
- async (): Promise> => {
- let settings = { ...DEFAULT_APP_SETTINGS };
-
- if (existsSync(settingsPath)) {
- try {
- const content = readFileSync(settingsPath, 'utf-8');
- settings = { ...settings, ...JSON.parse(content) };
- } catch {
- // Use defaults
- }
- }
-
- // If no manual autoBuildPath is set, try to auto-detect
- if (!settings.autoBuildPath) {
- const detectedPath = detectAutoBuildSourcePath();
- if (detectedPath) {
- settings.autoBuildPath = detectedPath;
- }
- }
-
- return { success: true, data: settings as AppSettings };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.SETTINGS_SAVE,
- async (_, settings: Partial): Promise => {
- try {
- let currentSettings = DEFAULT_APP_SETTINGS;
- if (existsSync(settingsPath)) {
- const content = readFileSync(settingsPath, 'utf-8');
- currentSettings = { ...currentSettings, ...JSON.parse(content) };
- }
-
- const newSettings = { ...currentSettings, ...settings };
- writeFileSync(settingsPath, JSON.stringify(newSettings, null, 2));
-
- // Apply Python path if changed
- if (settings.pythonPath || settings.autoBuildPath) {
- agentManager.configure(settings.pythonPath, settings.autoBuildPath);
- }
-
- return { success: true };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to save settings'
- };
- }
- }
- );
-
- // ============================================
- // Dialog Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.DIALOG_SELECT_DIRECTORY,
- async (): Promise => {
- const mainWindow = getMainWindow();
- if (!mainWindow) return null;
-
- const result = await dialog.showOpenDialog(mainWindow, {
- properties: ['openDirectory'],
- title: 'Select Project Directory'
- });
-
- if (result.canceled || result.filePaths.length === 0) {
- return null;
- }
-
- return result.filePaths[0];
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.DIALOG_CREATE_PROJECT_FOLDER,
- async (
- _,
- location: string,
- name: string,
- initGit: boolean
- ): Promise> => {
- try {
- // Validate inputs
- if (!location || !name) {
- return { success: false, error: 'Location and name are required' };
- }
-
- // Sanitize project name (convert to kebab-case, remove invalid chars)
- const sanitizedName = name
- .toLowerCase()
- .replace(/\s+/g, '-')
- .replace(/[^a-z0-9-_]/g, '')
- .replace(/-+/g, '-')
- .replace(/^-|-$/g, '');
-
- if (!sanitizedName) {
- return { success: false, error: 'Invalid project name' };
- }
-
- const projectPath = path.join(location, sanitizedName);
-
- // Check if folder already exists
- if (existsSync(projectPath)) {
- return { success: false, error: `Folder "${sanitizedName}" already exists at this location` };
- }
-
- // Create the directory
- mkdirSync(projectPath, { recursive: true });
-
- // Initialize git if requested
- let gitInitialized = false;
- if (initGit) {
- try {
- execSync('git init', { cwd: projectPath, stdio: 'ignore' });
- gitInitialized = true;
- } catch {
- // Git init failed, but folder was created - continue without git
- console.warn('Failed to initialize git repository');
- }
- }
-
- return {
- success: true,
- data: {
- path: projectPath,
- name: sanitizedName,
- gitInitialized
- }
- };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to create project folder'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.DIALOG_GET_DEFAULT_PROJECT_LOCATION,
- async (): Promise => {
- try {
- // Return user's home directory + common project folders
- const homeDir = app.getPath('home');
- const commonPaths = [
- path.join(homeDir, 'Projects'),
- path.join(homeDir, 'Developer'),
- path.join(homeDir, 'Code'),
- path.join(homeDir, 'Documents')
- ];
-
- // Return the first one that exists, or Documents as fallback
- for (const p of commonPaths) {
- if (existsSync(p)) {
- return p;
- }
- }
-
- return path.join(homeDir, 'Documents');
- } catch {
- return null;
- }
- }
- );
-
- // ============================================
- // App Info
- // ============================================
-
- ipcMain.handle(IPC_CHANNELS.APP_VERSION, async (): Promise => {
- return app.getVersion();
- });
-
- // ============================================
- // Terminal Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.TERMINAL_CREATE,
- async (_, options: TerminalCreateOptions): Promise => {
- return terminalManager.create(options);
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.TERMINAL_DESTROY,
- async (_, id: string): Promise => {
- return terminalManager.destroy(id);
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.TERMINAL_INPUT,
- (_, id: string, data: string) => {
- terminalManager.write(id, data);
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.TERMINAL_RESIZE,
- (_, id: string, cols: number, rows: number) => {
- terminalManager.resize(id, cols, rows);
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.TERMINAL_INVOKE_CLAUDE,
- (_, id: string, cwd?: string) => {
- terminalManager.invokeClaude(id, cwd);
- }
- );
-
- // Claude profile management (multi-account support)
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_PROFILES_GET,
- async (): Promise> => {
- try {
- const profileManager = getClaudeProfileManager();
- const settings = profileManager.getSettings();
- return { success: true, data: settings };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get Claude profiles'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_PROFILE_SAVE,
- async (_, profile: ClaudeProfile): Promise> => {
- try {
- const profileManager = getClaudeProfileManager();
-
- // If this is a new profile without an ID, generate one
- if (!profile.id) {
- profile.id = profileManager.generateProfileId(profile.name);
- }
-
- // Ensure config directory exists for non-default profiles
- if (!profile.isDefault && profile.configDir) {
- const { mkdirSync, existsSync } = await import('fs');
- if (!existsSync(profile.configDir)) {
- mkdirSync(profile.configDir, { recursive: true });
- }
- }
-
- const savedProfile = profileManager.saveProfile(profile);
- return { success: true, data: savedProfile };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to save Claude profile'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_PROFILE_DELETE,
- async (_, profileId: string): Promise => {
- try {
- const profileManager = getClaudeProfileManager();
- const success = profileManager.deleteProfile(profileId);
- if (!success) {
- return { success: false, error: 'Cannot delete default or last profile' };
- }
- return { success: true };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to delete Claude profile'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_PROFILE_RENAME,
- async (_, profileId: string, newName: string): Promise => {
- try {
- const profileManager = getClaudeProfileManager();
- const success = profileManager.renameProfile(profileId, newName);
- if (!success) {
- return { success: false, error: 'Profile not found or invalid name' };
- }
- return { success: true };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to rename Claude profile'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_PROFILE_SET_ACTIVE,
- async (_, profileId: string): Promise => {
- try {
- const profileManager = getClaudeProfileManager();
- const success = profileManager.setActiveProfile(profileId);
- if (!success) {
- return { success: false, error: 'Profile not found' };
- }
- return { success: true };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to set active Claude profile'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_PROFILE_SWITCH,
- async (_, terminalId: string, profileId: string): Promise => {
- try {
- const result = await terminalManager.switchClaudeProfile(terminalId, profileId);
- return result;
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to switch Claude profile'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_PROFILE_INITIALIZE,
- async (_, profileId: string): Promise => {
- try {
- const profileManager = getClaudeProfileManager();
- const profile = profileManager.getProfile(profileId);
- if (!profile) {
- return { success: false, error: 'Profile not found' };
- }
-
- // Ensure the config directory exists for non-default profiles
- if (!profile.isDefault && profile.configDir) {
- const { mkdirSync, existsSync } = await import('fs');
- if (!existsSync(profile.configDir)) {
- mkdirSync(profile.configDir, { recursive: true });
- console.log('[IPC] Created config directory:', profile.configDir);
- }
- }
-
- // Create a terminal and run claude setup-token there
- // This is needed because claude setup-token requires TTY/raw mode
- const terminalId = `claude-login-${profileId}-${Date.now()}`;
- const homeDir = process.env.HOME || process.env.USERPROFILE || '/tmp';
-
- console.log('[IPC] Initializing Claude profile:', {
- profileId,
- profileName: profile.name,
- configDir: profile.configDir,
- isDefault: profile.isDefault
- });
-
- // Create a new terminal for the login process
- await terminalManager.create({ id: terminalId, cwd: homeDir });
-
- // Wait a moment for the terminal to initialize
- await new Promise(resolve => setTimeout(resolve, 500));
-
- // Build the login command with the profile's config dir
- // Use export to ensure the variable persists, then run setup-token
- let loginCommand: string;
- if (!profile.isDefault && profile.configDir) {
- // Use export and run in subshell to ensure CLAUDE_CONFIG_DIR is properly set
- loginCommand = `export CLAUDE_CONFIG_DIR="${profile.configDir}" && echo "Config dir: $CLAUDE_CONFIG_DIR" && claude setup-token`;
- } else {
- loginCommand = 'claude setup-token';
- }
-
- console.log('[IPC] Sending login command to terminal:', loginCommand);
-
- // Write the login command to the terminal
- terminalManager.write(terminalId, `${loginCommand}\r`);
-
- // Notify the renderer that a login terminal was created
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send('claude-profile-login-terminal', {
- terminalId,
- profileId,
- profileName: profile.name
- });
- }
-
- return {
- success: true,
- data: {
- terminalId,
- message: `A terminal has been opened to authenticate "${profile.name}". Complete the OAuth flow in your browser, then copy the token shown in the terminal.`
- }
- };
- } catch (error) {
- console.error('[IPC] Failed to initialize Claude profile:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to initialize Claude profile'
- };
- }
- }
- );
-
- // Set OAuth token for a profile (used when capturing from terminal or manual input)
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_PROFILE_SET_TOKEN,
- async (_, profileId: string, token: string, email?: string): Promise => {
- try {
- const profileManager = getClaudeProfileManager();
- const success = profileManager.setProfileToken(profileId, token, email);
- if (!success) {
- return { success: false, error: 'Profile not found' };
- }
- return { success: true };
- } catch (error) {
- console.error('[IPC] Failed to set OAuth token:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to set OAuth token'
- };
- }
- }
- );
-
- // Get auto-switch settings
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_PROFILE_AUTO_SWITCH_SETTINGS,
- async (): Promise> => {
- try {
- const profileManager = getClaudeProfileManager();
- const settings = profileManager.getAutoSwitchSettings();
- return { success: true, data: settings };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get auto-switch settings'
- };
- }
- }
- );
-
- // Update auto-switch settings
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_PROFILE_UPDATE_AUTO_SWITCH,
- async (_, settings: Partial): Promise => {
- try {
- const profileManager = getClaudeProfileManager();
- profileManager.updateAutoSwitchSettings(settings);
- return { success: true };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to update auto-switch settings'
- };
- }
- }
- );
-
- // Fetch usage by sending /usage command to terminal
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_PROFILE_FETCH_USAGE,
- async (_, terminalId: string): Promise => {
- try {
- // Send /usage command to the terminal
- terminalManager.write(terminalId, '/usage\r');
- return { success: true };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to fetch usage'
- };
- }
- }
- );
-
- // Get best available profile
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_PROFILE_GET_BEST_PROFILE,
- async (_, excludeProfileId?: string): Promise> => {
- try {
- const profileManager = getClaudeProfileManager();
- const bestProfile = profileManager.getBestAvailableProfile(excludeProfileId);
- return { success: true, data: bestProfile };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get best profile'
- };
- }
- }
- );
-
- // Retry rate-limited operation with a different profile
- ipcMain.handle(
- IPC_CHANNELS.CLAUDE_RETRY_WITH_PROFILE,
- async (_, request: import('../shared/types').RetryWithProfileRequest): Promise => {
- try {
- const profileManager = getClaudeProfileManager();
-
- // Set the new active profile
- profileManager.setActiveProfile(request.profileId);
-
- // Get the project
- const project = projectStore.getProject(request.projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- // Retry based on the source
- switch (request.source) {
- case 'changelog':
- // The changelog UI will handle retrying by re-submitting the form
- // We just need to confirm the profile switch was successful
- return { success: true };
-
- case 'task':
- // For tasks, we would need to restart the task
- // This is complex and would need task state restoration
- return { success: true, data: { message: 'Please restart the task manually' } };
-
- case 'roadmap':
- // For roadmap, the UI can trigger a refresh
- return { success: true };
-
- case 'ideation':
- // For ideation, the UI can trigger a refresh
- return { success: true };
-
- default:
- return { success: true };
- }
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to retry with profile'
- };
- }
- }
- );
-
- // Terminal session management (persistence/restore)
- ipcMain.handle(
- IPC_CHANNELS.TERMINAL_GET_SESSIONS,
- async (_, projectPath: string): Promise> => {
- try {
- const sessions = terminalManager.getSavedSessions(projectPath);
- return { success: true, data: sessions };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get terminal sessions'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.TERMINAL_RESTORE_SESSION,
- async (_, session: import('../shared/types').TerminalSession, cols?: number, rows?: number): Promise> => {
- try {
- const result = await terminalManager.restore(session, cols, rows);
- return {
- success: result.success,
- data: {
- success: result.success,
- terminalId: session.id,
- outputBuffer: result.outputBuffer,
- error: result.error
- }
- };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to restore terminal session'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.TERMINAL_CLEAR_SESSIONS,
- async (_, projectPath: string): Promise => {
- try {
- terminalManager.clearSavedSessions(projectPath);
- return { success: true };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to clear terminal sessions'
- };
- }
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.TERMINAL_RESUME_CLAUDE,
- (_, id: string, sessionId?: string) => {
- terminalManager.resumeClaude(id, sessionId);
- }
- );
-
- // Get available session dates for a project
- ipcMain.handle(
- IPC_CHANNELS.TERMINAL_GET_SESSION_DATES,
- async (_, projectPath?: string) => {
- try {
- const dates = terminalManager.getAvailableSessionDates(projectPath);
- return { success: true, data: dates };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get session dates'
- };
- }
- }
- );
-
- // Get sessions for a specific date and project
- ipcMain.handle(
- IPC_CHANNELS.TERMINAL_GET_SESSIONS_FOR_DATE,
- async (_, date: string, projectPath: string) => {
- try {
- const sessions = terminalManager.getSessionsForDate(date, projectPath);
- return { success: true, data: sessions };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get sessions for date'
- };
- }
- }
- );
-
- // Restore all sessions from a specific date
- ipcMain.handle(
- IPC_CHANNELS.TERMINAL_RESTORE_FROM_DATE,
- async (_, date: string, projectPath: string, cols?: number, rows?: number) => {
- try {
- const result = await terminalManager.restoreSessionsFromDate(
- date,
- projectPath,
- cols || 80,
- rows || 24
- );
- return { success: true, data: result };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to restore sessions from date'
- };
- }
- }
- );
-
- // ============================================
- // Agent Manager Events → Renderer
- // ============================================
-
- agentManager.on('log', (taskId: string, log: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_LOG, taskId, log);
- }
- });
-
- agentManager.on('error', (taskId: string, error: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_ERROR, taskId, error);
- }
- });
-
- // Handle SDK rate limit events from agent manager
- agentManager.on('sdk-rate-limit', (rateLimitInfo: import('../shared/types').SDKRateLimitInfo) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.CLAUDE_SDK_RATE_LIMIT, rateLimitInfo);
- }
- });
-
- // Handle SDK rate limit events from title generator
- titleGenerator.on('sdk-rate-limit', (rateLimitInfo: import('../shared/types').SDKRateLimitInfo) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.CLAUDE_SDK_RATE_LIMIT, rateLimitInfo);
- }
- });
-
- agentManager.on('exit', (taskId: string, code: number | null, processType: import('./agent').ProcessType) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- // Stop file watcher
- fileWatcher.unwatch(taskId);
-
- // Determine new status based on process type and exit code
- // Flow: Planning → In Progress → AI Review (QA agent) → Human Review (QA passed)
- let newStatus: TaskStatus;
-
- if (processType === 'task-execution') {
- // Task execution completed (includes spec_runner → run.py chain)
- // Success (code 0) = QA agent signed off → Human Review
- // Failure = needs human attention → Human Review
- newStatus = 'human_review';
- } else if (processType === 'qa-process') {
- // QA retry process completed
- newStatus = 'human_review';
- } else if (processType === 'spec-creation') {
- // Pure spec creation (shouldn't happen with current flow, but handle it)
- // Stay in backlog/planning
- console.log(`[Task ${taskId}] Spec creation completed with code ${code}`);
- return;
- } else {
- // Unknown process type
- newStatus = 'human_review';
- }
-
- // Persist status to disk so it survives hot reload
- // This is a backup in case the Python backend didn't sync properly
- try {
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (task && project) {
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(project.path, specsBaseDir, task.specId);
- const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN);
-
- if (existsSync(planPath)) {
- const planContent = readFileSync(planPath, 'utf-8');
- const plan = JSON.parse(planContent);
-
- // Only update if not already set to a "further along" status
- // (e.g., don't override 'done' with 'human_review')
- const currentStatus = plan.status;
- const shouldUpdate = !currentStatus ||
- currentStatus === 'in_progress' ||
- currentStatus === 'ai_review' ||
- currentStatus === 'backlog' ||
- currentStatus === 'pending';
-
- if (shouldUpdate) {
- plan.status = newStatus;
- plan.planStatus = 'review';
- plan.updated_at = new Date().toISOString();
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- console.log(`[Task ${taskId}] Persisted status '${newStatus}' to implementation_plan.json`);
- }
- }
- }
- } catch (persistError) {
- console.error(`[Task ${taskId}] Failed to persist status:`, persistError);
- }
-
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- newStatus
- );
- }
- });
-
- agentManager.on('execution-progress', (taskId: string, progress: import('./agent').ExecutionProgressData) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_EXECUTION_PROGRESS, taskId, progress);
-
- // Auto-move task to AI Review when entering qa_review phase
- if (progress.phase === 'qa_review') {
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- 'ai_review'
- );
- }
- }
- });
-
- // ============================================
- // File Watcher Events → Renderer
- // ============================================
-
- fileWatcher.on('progress', (taskId: string, plan: ImplementationPlan) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_PROGRESS, taskId, plan);
- }
- });
-
- fileWatcher.on('error', (taskId: string, error: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_ERROR, taskId, error);
- }
- });
-
- // ============================================
- // Roadmap Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.ROADMAP_GET,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const roadmapPath = path.join(
- project.path,
- AUTO_BUILD_PATHS.ROADMAP_DIR,
- AUTO_BUILD_PATHS.ROADMAP_FILE
- );
-
- if (!existsSync(roadmapPath)) {
- return { success: true, data: null };
- }
-
- try {
- const content = readFileSync(roadmapPath, 'utf-8');
- const rawRoadmap = JSON.parse(content);
-
- // Transform snake_case to camelCase for frontend
- const roadmap: Roadmap = {
- id: rawRoadmap.id || `roadmap-${Date.now()}`,
- projectId,
- projectName: rawRoadmap.project_name || project.name,
- version: rawRoadmap.version || '1.0',
- vision: rawRoadmap.vision || '',
- targetAudience: {
- primary: rawRoadmap.target_audience?.primary || '',
- secondary: rawRoadmap.target_audience?.secondary || []
- },
- phases: (rawRoadmap.phases || []).map((phase: Record) => ({
- id: phase.id,
- name: phase.name,
- description: phase.description,
- order: phase.order,
- status: phase.status || 'planned',
- features: phase.features || [],
- milestones: (phase.milestones as Array> || []).map((m) => ({
- id: m.id,
- title: m.title,
- description: m.description,
- features: m.features || [],
- status: m.status || 'planned',
- targetDate: m.target_date ? new Date(m.target_date as string) : undefined
- }))
- })),
- features: (rawRoadmap.features || []).map((feature: Record) => ({
- id: feature.id,
- title: feature.title,
- description: feature.description,
- rationale: feature.rationale || '',
- priority: feature.priority || 'should',
- complexity: feature.complexity || 'medium',
- impact: feature.impact || 'medium',
- phaseId: feature.phase_id,
- dependencies: feature.dependencies || [],
- status: feature.status || 'idea',
- acceptanceCriteria: feature.acceptance_criteria || [],
- userStories: feature.user_stories || [],
- linkedSpecId: feature.linked_spec_id
- })),
- status: rawRoadmap.status || 'draft',
- createdAt: rawRoadmap.metadata?.created_at ? new Date(rawRoadmap.metadata.created_at) : new Date(),
- updatedAt: rawRoadmap.metadata?.updated_at ? new Date(rawRoadmap.metadata.updated_at) : new Date()
- };
-
- return { success: true, data: roadmap };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to read roadmap'
- };
- }
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.ROADMAP_GENERATE,
- (_, projectId: string) => {
- const mainWindow = getMainWindow();
- if (!mainWindow) return;
-
- const project = projectStore.getProject(projectId);
- if (!project) {
- mainWindow.webContents.send(
- IPC_CHANNELS.ROADMAP_ERROR,
- projectId,
- 'Project not found'
- );
- return;
- }
-
- // Start roadmap generation via agent manager
- agentManager.startRoadmapGeneration(projectId, project.path, false);
-
- // Send initial progress
- mainWindow.webContents.send(
- IPC_CHANNELS.ROADMAP_PROGRESS,
- projectId,
- {
- phase: 'analyzing',
- progress: 10,
- message: 'Analyzing project structure...'
- } as RoadmapGenerationStatus
- );
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.ROADMAP_REFRESH,
- (_, projectId: string) => {
- const mainWindow = getMainWindow();
- if (!mainWindow) return;
-
- const project = projectStore.getProject(projectId);
- if (!project) {
- mainWindow.webContents.send(
- IPC_CHANNELS.ROADMAP_ERROR,
- projectId,
- 'Project not found'
- );
- return;
- }
-
- // Start roadmap regeneration with refresh flag
- agentManager.startRoadmapGeneration(projectId, project.path, true);
-
- // Send initial progress
- mainWindow.webContents.send(
- IPC_CHANNELS.ROADMAP_PROGRESS,
- projectId,
- {
- phase: 'analyzing',
- progress: 10,
- message: 'Refreshing roadmap...'
- } as RoadmapGenerationStatus
- );
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.ROADMAP_UPDATE_FEATURE,
- async (
- _,
- projectId: string,
- featureId: string,
- status: RoadmapFeatureStatus
- ): Promise => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const roadmapPath = path.join(
- project.path,
- AUTO_BUILD_PATHS.ROADMAP_DIR,
- AUTO_BUILD_PATHS.ROADMAP_FILE
- );
-
- if (!existsSync(roadmapPath)) {
- return { success: false, error: 'Roadmap not found' };
- }
-
- try {
- const content = readFileSync(roadmapPath, 'utf-8');
- const roadmap = JSON.parse(content);
-
- // Find and update the feature
- const feature = roadmap.features?.find((f: { id: string }) => f.id === featureId);
- if (!feature) {
- return { success: false, error: 'Feature not found' };
- }
-
- feature.status = status;
- roadmap.metadata = roadmap.metadata || {};
- roadmap.metadata.updated_at = new Date().toISOString();
-
- writeFileSync(roadmapPath, JSON.stringify(roadmap, null, 2));
-
- return { success: true };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to update feature'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.ROADMAP_CONVERT_TO_SPEC,
- async (
- _,
- projectId: string,
- featureId: string
- ): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const roadmapPath = path.join(
- project.path,
- AUTO_BUILD_PATHS.ROADMAP_DIR,
- AUTO_BUILD_PATHS.ROADMAP_FILE
- );
-
- if (!existsSync(roadmapPath)) {
- return { success: false, error: 'Roadmap not found' };
- }
-
- try {
- const content = readFileSync(roadmapPath, 'utf-8');
- const roadmap = JSON.parse(content);
-
- // Find the feature
- const feature = roadmap.features?.find((f: { id: string }) => f.id === featureId);
- if (!feature) {
- return { success: false, error: 'Feature not found' };
- }
-
- // Build task description from feature
- const taskDescription = `# ${feature.title}
-
-${feature.description}
-
-## Rationale
-${feature.rationale || 'N/A'}
-
-## User Stories
-${(feature.user_stories || []).map((s: string) => `- ${s}`).join('\n') || 'N/A'}
-
-## Acceptance Criteria
-${(feature.acceptance_criteria || []).map((c: string) => `- [ ] ${c}`).join('\n') || 'N/A'}
-`;
-
- // Generate proper spec directory (like task creation)
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specsDir = path.join(project.path, specsBaseDir);
-
- // Ensure specs directory exists
- if (!existsSync(specsDir)) {
- mkdirSync(specsDir, { recursive: true });
- }
-
- // Find next available spec number
- let specNumber = 1;
- const existingDirs = existsSync(specsDir)
- ? readdirSync(specsDir, { withFileTypes: true })
- .filter(d => d.isDirectory())
- .map(d => d.name)
- : [];
- const existingNumbers = existingDirs
- .map(name => {
- const match = name.match(/^(\d+)/);
- return match ? parseInt(match[1], 10) : 0;
- })
- .filter(n => n > 0);
- if (existingNumbers.length > 0) {
- specNumber = Math.max(...existingNumbers) + 1;
- }
-
- // Create spec ID with zero-padded number and slugified title
- const slugifiedTitle = feature.title
- .toLowerCase()
- .replace(/[^a-z0-9]+/g, '-')
- .replace(/^-|-$/g, '')
- .substring(0, 50);
- const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`;
-
- // Create spec directory
- const specDir = path.join(specsDir, specId);
- mkdirSync(specDir, { recursive: true });
-
- // Create initial implementation_plan.json
- const now = new Date().toISOString();
- const implementationPlan = {
- feature: feature.title,
- description: taskDescription,
- created_at: now,
- updated_at: now,
- status: 'pending',
- phases: []
- };
- writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN), JSON.stringify(implementationPlan, null, 2));
-
- // Create requirements.json
- const requirements = {
- task_description: taskDescription,
- workflow_type: 'feature'
- };
- writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS), JSON.stringify(requirements, null, 2));
-
- // Build metadata
- const metadata: TaskMetadata = {
- sourceType: 'roadmap',
- featureId: feature.id,
- category: 'feature'
- };
- writeFileSync(path.join(specDir, 'task_metadata.json'), JSON.stringify(metadata, null, 2));
-
- // Start spec creation with the existing spec directory
- agentManager.startSpecCreation(specId, project.path, taskDescription, specDir, metadata);
-
- // Update feature with linked spec
- feature.status = 'planned';
- feature.linked_spec_id = specId;
- roadmap.metadata = roadmap.metadata || {};
- roadmap.metadata.updated_at = new Date().toISOString();
- writeFileSync(roadmapPath, JSON.stringify(roadmap, null, 2));
-
- // Create task object
- const task: Task = {
- id: specId,
- specId: specId,
- projectId,
- title: feature.title,
- description: taskDescription,
- status: 'backlog',
- subtasks: [],
- logs: [],
- metadata,
- createdAt: new Date(),
- updatedAt: new Date()
- };
-
- return { success: true, data: task };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to convert feature to spec'
- };
- }
- }
- );
-
- // ============================================
- // Roadmap Agent Events → Renderer
- // ============================================
-
- agentManager.on('roadmap-progress', (projectId: string, status: RoadmapGenerationStatus) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.ROADMAP_PROGRESS, projectId, status);
- }
- });
-
- agentManager.on('roadmap-complete', (projectId: string, roadmap: Roadmap) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.ROADMAP_COMPLETE, projectId, roadmap);
- }
- });
-
- agentManager.on('roadmap-error', (projectId: string, error: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.ROADMAP_ERROR, projectId, error);
- }
- });
-
- // ============================================
- // Context Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.CONTEXT_GET,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- try {
- // Load project index
- let projectIndex: ProjectIndex | null = null;
- const indexPath = path.join(project.path, AUTO_BUILD_PATHS.PROJECT_INDEX);
- if (existsSync(indexPath)) {
- const content = readFileSync(indexPath, 'utf-8');
- projectIndex = JSON.parse(content);
- }
-
- // Load graphiti state from most recent spec or project root
- let memoryState: GraphitiMemoryState | null = null;
- let memoryStatus: GraphitiMemoryStatus = {
- enabled: false,
- available: false,
- reason: 'Graphiti not configured'
- };
-
- // Check for graphiti state in specs
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specsDir = path.join(project.path, specsBaseDir);
- if (existsSync(specsDir)) {
- const specDirs = readdirSync(specsDir)
- .filter((f: string) => {
- const specPath = path.join(specsDir, f);
- return statSync(specPath).isDirectory();
- })
- .sort()
- .reverse();
-
- for (const specDir of specDirs) {
- const statePath = path.join(specsDir, specDir, AUTO_BUILD_PATHS.GRAPHITI_STATE);
- if (existsSync(statePath)) {
- const stateContent = readFileSync(statePath, 'utf-8');
- memoryState = JSON.parse(stateContent);
-
- // If we found a state, update memory status
- if (memoryState?.initialized) {
- memoryStatus = {
- enabled: true,
- available: true,
- database: memoryState.database || 'auto_build_memory',
- host: process.env.GRAPHITI_FALKORDB_HOST || 'localhost',
- port: parseInt(process.env.GRAPHITI_FALKORDB_PORT || '6380', 10)
- };
- }
- break;
- }
- }
- }
-
- // Check environment for Graphiti config if not found in specs
- if (!memoryState) {
- // Load project .env file and global settings to check for Graphiti config
- let projectEnvVars: Record = {};
- if (project.autoBuildPath) {
- const projectEnvPath = path.join(project.path, project.autoBuildPath, '.env');
- if (existsSync(projectEnvPath)) {
- try {
- const envContent = readFileSync(projectEnvPath, 'utf-8');
- // Parse .env file inline - handle both Unix and Windows line endings
- for (const line of envContent.split(/\r?\n/)) {
- const trimmed = line.trim();
- if (!trimmed || trimmed.startsWith('#')) continue;
- const eqIndex = trimmed.indexOf('=');
- if (eqIndex > 0) {
- const key = trimmed.substring(0, eqIndex).trim();
- let value = trimmed.substring(eqIndex + 1).trim();
- if ((value.startsWith('"') && value.endsWith('"')) ||
- (value.startsWith("'") && value.endsWith("'"))) {
- value = value.slice(1, -1);
- }
- projectEnvVars[key] = value;
- }
- }
- } catch {
- // Continue with empty vars
- }
- }
- }
-
- // Load global settings for OpenAI API key fallback
- let globalOpenAIKey: string | undefined;
- if (existsSync(settingsPath)) {
- try {
- const settingsContent = readFileSync(settingsPath, 'utf-8');
- const globalSettings = JSON.parse(settingsContent);
- globalOpenAIKey = globalSettings.globalOpenAIApiKey;
- } catch {
- // Continue without global settings
- }
- }
-
- // Check for Graphiti config: project .env > process.env
- const graphitiEnabled =
- projectEnvVars['GRAPHITI_ENABLED']?.toLowerCase() === 'true' ||
- process.env.GRAPHITI_ENABLED?.toLowerCase() === 'true';
-
- // Check for OpenAI key: project .env > global settings > process.env
- const hasOpenAI =
- !!projectEnvVars['OPENAI_API_KEY'] ||
- !!globalOpenAIKey ||
- !!process.env.OPENAI_API_KEY;
-
- // Get Graphiti connection details from project .env or process.env
- const graphitiHost = projectEnvVars['GRAPHITI_FALKORDB_HOST'] || process.env.GRAPHITI_FALKORDB_HOST || 'localhost';
- const graphitiPort = parseInt(projectEnvVars['GRAPHITI_FALKORDB_PORT'] || process.env.GRAPHITI_FALKORDB_PORT || '6380', 10);
- const graphitiDatabase = projectEnvVars['GRAPHITI_DATABASE'] || process.env.GRAPHITI_DATABASE || 'auto_build_memory';
-
- if (graphitiEnabled && hasOpenAI) {
- memoryStatus = {
- enabled: true,
- available: true,
- host: graphitiHost,
- port: graphitiPort,
- database: graphitiDatabase
- };
- } else if (graphitiEnabled && !hasOpenAI) {
- memoryStatus = {
- enabled: true,
- available: false,
- reason: 'OPENAI_API_KEY not set (required for Graphiti embeddings)'
- };
- }
- }
-
- // Load recent memories from file-based memory (session insights)
- const recentMemories: MemoryEpisode[] = [];
- if (existsSync(specsDir)) {
- const recentSpecDirs = readdirSync(specsDir)
- .filter((f: string) => {
- const specPath = path.join(specsDir, f);
- return statSync(specPath).isDirectory();
- })
- .sort()
- .reverse()
- .slice(0, 10); // Last 10 specs
-
- for (const specDir of recentSpecDirs) {
- const memoryDir = path.join(specsDir, specDir, 'memory');
- if (existsSync(memoryDir)) {
- // Load session insights from session_insights subdirectory
- const sessionInsightsDir = path.join(memoryDir, 'session_insights');
- if (existsSync(sessionInsightsDir)) {
- const sessionFiles = readdirSync(sessionInsightsDir)
- .filter((f: string) => f.startsWith('session_') && f.endsWith('.json'))
- .sort()
- .reverse();
-
- for (const sessionFile of sessionFiles.slice(0, 3)) {
- try {
- const sessionPath = path.join(sessionInsightsDir, sessionFile);
- const sessionContent = readFileSync(sessionPath, 'utf-8');
- const sessionData = JSON.parse(sessionContent);
-
- // Session files have: session_number, timestamp, subtasks_completed,
- // discoveries, what_worked, what_failed, recommendations_for_next_session
- if (sessionData.session_number !== undefined) {
- recentMemories.push({
- id: `${specDir}-${sessionFile}`,
- type: 'session_insight',
- timestamp: sessionData.timestamp || new Date().toISOString(),
- content: JSON.stringify({
- discoveries: sessionData.discoveries,
- what_worked: sessionData.what_worked,
- what_failed: sessionData.what_failed,
- recommendations: sessionData.recommendations_for_next_session,
- subtasks_completed: sessionData.subtasks_completed
- }, null, 2),
- session_number: sessionData.session_number
- });
- }
- } catch {
- // Skip invalid files
- }
- }
- }
-
- // Also load codebase_map.json as a memory item
- const codebaseMapPath = path.join(memoryDir, 'codebase_map.json');
- if (existsSync(codebaseMapPath)) {
- try {
- const mapContent = readFileSync(codebaseMapPath, 'utf-8');
- const mapData = JSON.parse(mapContent);
- if (mapData.discovered_files && Object.keys(mapData.discovered_files).length > 0) {
- recentMemories.push({
- id: `${specDir}-codebase_map`,
- type: 'codebase_map',
- timestamp: mapData.last_updated || new Date().toISOString(),
- content: JSON.stringify(mapData.discovered_files, null, 2),
- session_number: undefined
- });
- }
- } catch {
- // Skip invalid files
- }
- }
- }
- }
- }
-
- return {
- success: true,
- data: {
- projectIndex,
- memoryStatus,
- memoryState,
- recentMemories: recentMemories.slice(0, 20),
- isLoading: false
- }
- };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to load project context'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CONTEXT_REFRESH_INDEX,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- try {
- // Run the analyzer script to regenerate project_index.json
- const autoBuildSource = getAutoBuildSourcePath();
-
- if (!autoBuildSource) {
- return {
- success: false,
- error: 'Auto-build source path not configured'
- };
- }
-
- const analyzerPath = path.join(autoBuildSource, 'analyzer.py');
- const indexOutputPath = path.join(project.path, AUTO_BUILD_PATHS.PROJECT_INDEX);
-
- // Run analyzer
- await new Promise((resolve, reject) => {
- const proc = spawn('python', [
- analyzerPath,
- '--project-dir', project.path,
- '--output', indexOutputPath
- ], {
- cwd: project.path,
- env: { ...process.env }
- });
-
- proc.on('close', (code: number) => {
- if (code === 0) {
- resolve();
- } else {
- reject(new Error(`Analyzer exited with code ${code}`));
- }
- });
-
- proc.on('error', reject);
- });
-
- // Read the new index
- if (existsSync(indexOutputPath)) {
- const content = readFileSync(indexOutputPath, 'utf-8');
- const projectIndex = JSON.parse(content);
- return { success: true, data: projectIndex };
- }
-
- return { success: false, error: 'Failed to generate project index' };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to refresh project index'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CONTEXT_MEMORY_STATUS,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- // Load project .env file to check for Graphiti config
- let projectEnvVars: Record = {};
- if (project.autoBuildPath) {
- const projectEnvPath = path.join(project.path, project.autoBuildPath, '.env');
- if (existsSync(projectEnvPath)) {
- try {
- const envContent = readFileSync(projectEnvPath, 'utf-8');
- // Parse .env file inline - handle both Unix and Windows line endings
- for (const line of envContent.split(/\r?\n/)) {
- const trimmed = line.trim();
- if (!trimmed || trimmed.startsWith('#')) continue;
- const eqIndex = trimmed.indexOf('=');
- if (eqIndex > 0) {
- const key = trimmed.substring(0, eqIndex).trim();
- let value = trimmed.substring(eqIndex + 1).trim();
- if ((value.startsWith('"') && value.endsWith('"')) ||
- (value.startsWith("'") && value.endsWith("'"))) {
- value = value.slice(1, -1);
- }
- projectEnvVars[key] = value;
- }
- }
- } catch {
- // Continue with empty vars
- }
- }
- }
-
- // Load global settings for OpenAI API key fallback
- let globalOpenAIKey: string | undefined;
- if (existsSync(settingsPath)) {
- try {
- const settingsContent = readFileSync(settingsPath, 'utf-8');
- const globalSettings = JSON.parse(settingsContent);
- globalOpenAIKey = globalSettings.globalOpenAIApiKey;
- } catch {
- // Continue without global settings
- }
- }
-
- // Check for Graphiti config: project .env > process.env
- const graphitiEnabled =
- projectEnvVars['GRAPHITI_ENABLED']?.toLowerCase() === 'true' ||
- process.env.GRAPHITI_ENABLED?.toLowerCase() === 'true';
-
- // Check for OpenAI key: project .env > global settings > process.env
- const hasOpenAI =
- !!projectEnvVars['OPENAI_API_KEY'] ||
- !!globalOpenAIKey ||
- !!process.env.OPENAI_API_KEY;
-
- // Get Graphiti connection details from project .env or process.env
- const graphitiHost = projectEnvVars['GRAPHITI_FALKORDB_HOST'] || process.env.GRAPHITI_FALKORDB_HOST || 'localhost';
- const graphitiPort = parseInt(projectEnvVars['GRAPHITI_FALKORDB_PORT'] || process.env.GRAPHITI_FALKORDB_PORT || '6380', 10);
- const graphitiDatabase = projectEnvVars['GRAPHITI_DATABASE'] || process.env.GRAPHITI_DATABASE || 'auto_build_memory';
-
- if (!graphitiEnabled) {
- return {
- success: true,
- data: {
- enabled: false,
- available: false,
- reason: 'GRAPHITI_ENABLED not set to true'
- }
- };
- }
-
- if (!hasOpenAI) {
- return {
- success: true,
- data: {
- enabled: true,
- available: false,
- reason: 'OPENAI_API_KEY not set (required for embeddings)'
- }
- };
- }
-
- return {
- success: true,
- data: {
- enabled: true,
- available: true,
- host: graphitiHost,
- port: graphitiPort,
- database: graphitiDatabase
- }
- };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CONTEXT_SEARCH_MEMORIES,
- async (_, projectId: string, query: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- // For now, do simple text search in file-based memories
- // Graphiti search would require running Python subprocess
- const results: ContextSearchResult[] = [];
- const queryLower = query.toLowerCase();
-
- // Get specs directory path
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specsDir = path.join(project.path, specsBaseDir);
- if (existsSync(specsDir)) {
- const allSpecDirs = readdirSync(specsDir)
- .filter((f: string) => {
- const specPath = path.join(specsDir, f);
- return statSync(specPath).isDirectory();
- });
-
- for (const specDir of allSpecDirs) {
- const memoryDir = path.join(specsDir, specDir, 'memory');
- if (existsSync(memoryDir)) {
- const memoryFiles = readdirSync(memoryDir)
- .filter((f: string) => f.endsWith('.json'));
-
- for (const memFile of memoryFiles) {
- try {
- const memPath = path.join(memoryDir, memFile);
- const memContent = readFileSync(memPath, 'utf-8');
-
- if (memContent.toLowerCase().includes(queryLower)) {
- const memData = JSON.parse(memContent);
- results.push({
- content: JSON.stringify(memData.insights || memData, null, 2),
- score: 1.0,
- type: 'session_insight'
- });
- }
- } catch {
- // Skip invalid files
- }
- }
- }
- }
- }
-
- return { success: true, data: results.slice(0, 20) };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CONTEXT_GET_MEMORIES,
- async (_, projectId: string, limit: number = 20): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const memories: MemoryEpisode[] = [];
-
- // Get specs directory path
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specsDir = path.join(project.path, specsBaseDir);
-
- if (existsSync(specsDir)) {
- const sortedSpecDirs = readdirSync(specsDir)
- .filter((f: string) => {
- const specPath = path.join(specsDir, f);
- return statSync(specPath).isDirectory();
- })
- .sort()
- .reverse();
-
- for (const specDir of sortedSpecDirs) {
- const memoryDir = path.join(specsDir, specDir, 'memory');
- if (existsSync(memoryDir)) {
- const memoryFiles = readdirSync(memoryDir)
- .filter((f: string) => f.endsWith('.json'))
- .sort()
- .reverse();
-
- for (const memFile of memoryFiles) {
- try {
- const memPath = path.join(memoryDir, memFile);
- const memContent = readFileSync(memPath, 'utf-8');
- const memData = JSON.parse(memContent);
-
- memories.push({
- id: `${specDir}-${memFile}`,
- type: memData.type || 'session_insight',
- timestamp: memData.timestamp || new Date().toISOString(),
- content: JSON.stringify(memData.insights || memData, null, 2),
- session_number: memData.session_number
- });
-
- if (memories.length >= limit) {
- break;
- }
- } catch {
- // Skip invalid files
- }
- }
- }
-
- if (memories.length >= limit) {
- break;
- }
- }
- }
-
- return { success: true, data: memories };
- }
- );
-
- // ============================================
- // Environment Configuration Operations
- // ============================================
-
- /**
- * Parse .env file into key-value object
- */
- const parseEnvFile = (content: string): Record => {
- const result: Record = {};
- const lines = content.split('\n');
-
- for (const line of lines) {
- const trimmed = line.trim();
- // Skip empty lines and comments
- if (!trimmed || trimmed.startsWith('#')) continue;
-
- const equalsIndex = trimmed.indexOf('=');
- if (equalsIndex > 0) {
- const key = trimmed.substring(0, equalsIndex).trim();
- let value = trimmed.substring(equalsIndex + 1).trim();
- // Remove quotes if present
- if ((value.startsWith('"') && value.endsWith('"')) ||
- (value.startsWith("'") && value.endsWith("'"))) {
- value = value.slice(1, -1);
- }
- result[key] = value;
- }
- }
- return result;
- };
-
- /**
- * Generate .env file content from config
- */
- const generateEnvContent = (
- config: Partial,
- existingContent?: string
- ): string => {
- // Parse existing content to preserve comments and structure
- const existingVars = existingContent ? parseEnvFile(existingContent) : {};
-
- // Update with new values
- if (config.claudeOAuthToken !== undefined) {
- existingVars['CLAUDE_CODE_OAUTH_TOKEN'] = config.claudeOAuthToken;
- }
- if (config.autoBuildModel !== undefined) {
- existingVars['AUTO_BUILD_MODEL'] = config.autoBuildModel;
- }
- if (config.linearApiKey !== undefined) {
- existingVars['LINEAR_API_KEY'] = config.linearApiKey;
- }
- if (config.linearTeamId !== undefined) {
- existingVars['LINEAR_TEAM_ID'] = config.linearTeamId;
- }
- if (config.linearProjectId !== undefined) {
- existingVars['LINEAR_PROJECT_ID'] = config.linearProjectId;
- }
- if (config.linearRealtimeSync !== undefined) {
- existingVars['LINEAR_REALTIME_SYNC'] = config.linearRealtimeSync ? 'true' : 'false';
- }
- // GitHub Integration
- if (config.githubToken !== undefined) {
- existingVars['GITHUB_TOKEN'] = config.githubToken;
- }
- if (config.githubRepo !== undefined) {
- existingVars['GITHUB_REPO'] = config.githubRepo;
- }
- if (config.githubAutoSync !== undefined) {
- existingVars['GITHUB_AUTO_SYNC'] = config.githubAutoSync ? 'true' : 'false';
- }
- if (config.graphitiEnabled !== undefined) {
- existingVars['GRAPHITI_ENABLED'] = config.graphitiEnabled ? 'true' : 'false';
- }
- if (config.openaiApiKey !== undefined) {
- existingVars['OPENAI_API_KEY'] = config.openaiApiKey;
- }
- if (config.graphitiFalkorDbHost !== undefined) {
- existingVars['GRAPHITI_FALKORDB_HOST'] = config.graphitiFalkorDbHost;
- }
- if (config.graphitiFalkorDbPort !== undefined) {
- existingVars['GRAPHITI_FALKORDB_PORT'] = String(config.graphitiFalkorDbPort);
- }
- if (config.graphitiFalkorDbPassword !== undefined) {
- existingVars['GRAPHITI_FALKORDB_PASSWORD'] = config.graphitiFalkorDbPassword;
- }
- if (config.graphitiDatabase !== undefined) {
- existingVars['GRAPHITI_DATABASE'] = config.graphitiDatabase;
- }
- if (config.enableFancyUi !== undefined) {
- existingVars['ENABLE_FANCY_UI'] = config.enableFancyUi ? 'true' : 'false';
- }
-
- // Generate content with sections
- let content = `# Auto Claude Framework Environment Variables
-# Managed by Auto Claude UI
-
-# Claude Code OAuth Token (REQUIRED)
-CLAUDE_CODE_OAUTH_TOKEN=${existingVars['CLAUDE_CODE_OAUTH_TOKEN'] || ''}
-
-# Model override (OPTIONAL)
-${existingVars['AUTO_BUILD_MODEL'] ? `AUTO_BUILD_MODEL=${existingVars['AUTO_BUILD_MODEL']}` : '# AUTO_BUILD_MODEL=claude-opus-4-5-20251101'}
-
-# =============================================================================
-# LINEAR INTEGRATION (OPTIONAL)
-# =============================================================================
-${existingVars['LINEAR_API_KEY'] ? `LINEAR_API_KEY=${existingVars['LINEAR_API_KEY']}` : '# LINEAR_API_KEY='}
-${existingVars['LINEAR_TEAM_ID'] ? `LINEAR_TEAM_ID=${existingVars['LINEAR_TEAM_ID']}` : '# LINEAR_TEAM_ID='}
-${existingVars['LINEAR_PROJECT_ID'] ? `LINEAR_PROJECT_ID=${existingVars['LINEAR_PROJECT_ID']}` : '# LINEAR_PROJECT_ID='}
-${existingVars['LINEAR_REALTIME_SYNC'] !== undefined ? `LINEAR_REALTIME_SYNC=${existingVars['LINEAR_REALTIME_SYNC']}` : '# LINEAR_REALTIME_SYNC=false'}
-
-# =============================================================================
-# GITHUB INTEGRATION (OPTIONAL)
-# =============================================================================
-${existingVars['GITHUB_TOKEN'] ? `GITHUB_TOKEN=${existingVars['GITHUB_TOKEN']}` : '# GITHUB_TOKEN='}
-${existingVars['GITHUB_REPO'] ? `GITHUB_REPO=${existingVars['GITHUB_REPO']}` : '# GITHUB_REPO=owner/repo'}
-${existingVars['GITHUB_AUTO_SYNC'] !== undefined ? `GITHUB_AUTO_SYNC=${existingVars['GITHUB_AUTO_SYNC']}` : '# GITHUB_AUTO_SYNC=false'}
-
-# =============================================================================
-# UI SETTINGS (OPTIONAL)
-# =============================================================================
-${existingVars['ENABLE_FANCY_UI'] !== undefined ? `ENABLE_FANCY_UI=${existingVars['ENABLE_FANCY_UI']}` : '# ENABLE_FANCY_UI=true'}
-
-# =============================================================================
-# GRAPHITI MEMORY INTEGRATION (OPTIONAL)
-# =============================================================================
-${existingVars['GRAPHITI_ENABLED'] ? `GRAPHITI_ENABLED=${existingVars['GRAPHITI_ENABLED']}` : '# GRAPHITI_ENABLED=false'}
-${existingVars['OPENAI_API_KEY'] ? `OPENAI_API_KEY=${existingVars['OPENAI_API_KEY']}` : '# OPENAI_API_KEY='}
-${existingVars['GRAPHITI_FALKORDB_HOST'] ? `GRAPHITI_FALKORDB_HOST=${existingVars['GRAPHITI_FALKORDB_HOST']}` : '# GRAPHITI_FALKORDB_HOST=localhost'}
-${existingVars['GRAPHITI_FALKORDB_PORT'] ? `GRAPHITI_FALKORDB_PORT=${existingVars['GRAPHITI_FALKORDB_PORT']}` : '# GRAPHITI_FALKORDB_PORT=6380'}
-${existingVars['GRAPHITI_FALKORDB_PASSWORD'] ? `GRAPHITI_FALKORDB_PASSWORD=${existingVars['GRAPHITI_FALKORDB_PASSWORD']}` : '# GRAPHITI_FALKORDB_PASSWORD='}
-${existingVars['GRAPHITI_DATABASE'] ? `GRAPHITI_DATABASE=${existingVars['GRAPHITI_DATABASE']}` : '# GRAPHITI_DATABASE=auto_build_memory'}
-`;
-
- return content;
- };
-
- ipcMain.handle(
- IPC_CHANNELS.ENV_GET,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- if (!project.autoBuildPath) {
- return { success: false, error: 'Project not initialized' };
- }
-
- const envPath = path.join(project.path, project.autoBuildPath, '.env');
-
- // Load global settings for fallbacks
- let globalSettings: AppSettings = { ...DEFAULT_APP_SETTINGS };
- if (existsSync(settingsPath)) {
- try {
- const content = readFileSync(settingsPath, 'utf-8');
- globalSettings = { ...globalSettings, ...JSON.parse(content) };
- } catch {
- // Use defaults
- }
- }
-
- // Default config
- const config: ProjectEnvConfig = {
- claudeAuthStatus: 'not_configured',
- linearEnabled: false,
- githubEnabled: false,
- graphitiEnabled: false,
- enableFancyUi: true,
- claudeTokenIsGlobal: false,
- openaiKeyIsGlobal: false
- };
-
- // Parse project-specific .env if it exists
- let vars: Record = {};
- if (existsSync(envPath)) {
- try {
- const content = readFileSync(envPath, 'utf-8');
- vars = parseEnvFile(content);
- } catch {
- // Continue with empty vars
- }
- }
-
- // Claude OAuth Token: project-specific takes precedence, then global
- if (vars['CLAUDE_CODE_OAUTH_TOKEN']) {
- config.claudeOAuthToken = vars['CLAUDE_CODE_OAUTH_TOKEN'];
- config.claudeAuthStatus = 'token_set';
- config.claudeTokenIsGlobal = false;
- } else if (globalSettings.globalClaudeOAuthToken) {
- config.claudeOAuthToken = globalSettings.globalClaudeOAuthToken;
- config.claudeAuthStatus = 'token_set';
- config.claudeTokenIsGlobal = true;
- }
-
- if (vars['AUTO_BUILD_MODEL']) {
- config.autoBuildModel = vars['AUTO_BUILD_MODEL'];
- }
-
- if (vars['LINEAR_API_KEY']) {
- config.linearEnabled = true;
- config.linearApiKey = vars['LINEAR_API_KEY'];
- }
- if (vars['LINEAR_TEAM_ID']) {
- config.linearTeamId = vars['LINEAR_TEAM_ID'];
- }
- if (vars['LINEAR_PROJECT_ID']) {
- config.linearProjectId = vars['LINEAR_PROJECT_ID'];
- }
- if (vars['LINEAR_REALTIME_SYNC']?.toLowerCase() === 'true') {
- config.linearRealtimeSync = true;
- }
-
- // GitHub config
- if (vars['GITHUB_TOKEN']) {
- config.githubEnabled = true;
- config.githubToken = vars['GITHUB_TOKEN'];
- }
- if (vars['GITHUB_REPO']) {
- config.githubRepo = vars['GITHUB_REPO'];
- }
- if (vars['GITHUB_AUTO_SYNC']?.toLowerCase() === 'true') {
- config.githubAutoSync = true;
- }
-
- if (vars['GRAPHITI_ENABLED']?.toLowerCase() === 'true') {
- config.graphitiEnabled = true;
- }
-
- // OpenAI API Key: project-specific takes precedence, then global
- if (vars['OPENAI_API_KEY']) {
- config.openaiApiKey = vars['OPENAI_API_KEY'];
- config.openaiKeyIsGlobal = false;
- } else if (globalSettings.globalOpenAIApiKey) {
- config.openaiApiKey = globalSettings.globalOpenAIApiKey;
- config.openaiKeyIsGlobal = true;
- }
-
- if (vars['GRAPHITI_FALKORDB_HOST']) {
- config.graphitiFalkorDbHost = vars['GRAPHITI_FALKORDB_HOST'];
- }
- if (vars['GRAPHITI_FALKORDB_PORT']) {
- config.graphitiFalkorDbPort = parseInt(vars['GRAPHITI_FALKORDB_PORT'], 10);
- }
- if (vars['GRAPHITI_FALKORDB_PASSWORD']) {
- config.graphitiFalkorDbPassword = vars['GRAPHITI_FALKORDB_PASSWORD'];
- }
- if (vars['GRAPHITI_DATABASE']) {
- config.graphitiDatabase = vars['GRAPHITI_DATABASE'];
- }
-
- if (vars['ENABLE_FANCY_UI']?.toLowerCase() === 'false') {
- config.enableFancyUi = false;
- }
-
- return { success: true, data: config };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.ENV_UPDATE,
- async (_, projectId: string, config: Partial): Promise => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- if (!project.autoBuildPath) {
- return { success: false, error: 'Project not initialized' };
- }
-
- const envPath = path.join(project.path, project.autoBuildPath, '.env');
-
- try {
- // Read existing content if file exists
- let existingContent: string | undefined;
- if (existsSync(envPath)) {
- existingContent = readFileSync(envPath, 'utf-8');
- }
-
- // Generate new content
- const newContent = generateEnvContent(config, existingContent);
-
- // Write to file
- writeFileSync(envPath, newContent);
-
- return { success: true };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to update .env file'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.ENV_CHECK_CLAUDE_AUTH,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- try {
- // Check if Claude CLI is available and authenticated
- const result = await new Promise((resolve) => {
- const proc = spawn('claude', ['--version'], {
- cwd: project.path,
- env: { ...process.env },
- shell: true
- });
-
- let stdout = '';
- let stderr = '';
-
- proc.stdout?.on('data', (data: Buffer) => {
- stdout += data.toString();
- });
-
- proc.stderr?.on('data', (data: Buffer) => {
- stderr += data.toString();
- });
-
- proc.on('close', (code: number | null) => {
- if (code === 0) {
- // Claude CLI is available, check if authenticated
- // Run a simple command that requires auth
- const authCheck = spawn('claude', ['api', '--help'], {
- cwd: project.path,
- env: { ...process.env },
- shell: true
- });
-
- authCheck.on('close', (authCode: number | null) => {
- resolve({
- success: true,
- authenticated: authCode === 0
- });
- });
-
- authCheck.on('error', () => {
- resolve({
- success: true,
- authenticated: false,
- error: 'Could not verify authentication'
- });
- });
- } else {
- resolve({
- success: false,
- authenticated: false,
- error: 'Claude CLI not found. Please install it first.'
- });
- }
- });
-
- proc.on('error', () => {
- resolve({
- success: false,
- authenticated: false,
- error: 'Claude CLI not found. Please install it first.'
- });
- });
- });
-
- return { success: true, data: result };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to check Claude auth'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.ENV_INVOKE_CLAUDE_SETUP,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- try {
- // Run claude setup-token which will open browser for OAuth
- const result = await new Promise((resolve) => {
- const proc = spawn('claude', ['setup-token'], {
- cwd: project.path,
- env: { ...process.env },
- shell: true,
- stdio: 'inherit' // This allows the terminal to handle the interactive auth
- });
-
- proc.on('close', (code: number | null) => {
- if (code === 0) {
- resolve({
- success: true,
- authenticated: true
- });
- } else {
- resolve({
- success: false,
- authenticated: false,
- error: 'Setup cancelled or failed'
- });
- }
- });
-
- proc.on('error', (err: Error) => {
- resolve({
- success: false,
- authenticated: false,
- error: err.message
- });
- });
- });
-
- return { success: true, data: result };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to invoke Claude setup'
- };
- }
- }
- );
-
- // ============================================
- // Linear Integration Operations
- // ============================================
-
- /**
- * Helper to get Linear API key from project env
- */
- const getLinearApiKey = (project: Project): string | null => {
- if (!project.autoBuildPath) return null;
- const envPath = path.join(project.path, project.autoBuildPath, '.env');
- if (!existsSync(envPath)) return null;
-
- try {
- const content = readFileSync(envPath, 'utf-8');
- const vars = parseEnvFile(content);
- return vars['LINEAR_API_KEY'] || null;
- } catch {
- return null;
- }
- };
-
- /**
- * Make a request to the Linear API
- */
- const linearGraphQL = async (
- apiKey: string,
- query: string,
- variables?: Record
- ): Promise => {
- const response = await fetch('https://api.linear.app/graphql', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': apiKey
- },
- body: JSON.stringify({ query, variables })
- });
-
- if (!response.ok) {
- throw new Error(`Linear API error: ${response.status} ${response.statusText}`);
- }
-
- const result = await response.json();
- if (result.errors) {
- throw new Error(result.errors[0]?.message || 'Linear API error');
- }
-
- return result.data;
- };
-
- ipcMain.handle(
- IPC_CHANNELS.LINEAR_CHECK_CONNECTION,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const apiKey = getLinearApiKey(project);
- if (!apiKey) {
- return {
- success: true,
- data: {
- connected: false,
- error: 'No Linear API key configured'
- }
- };
- }
-
- try {
- const query = `
- query {
- viewer {
- id
- name
- }
- teams {
- nodes {
- id
- name
- key
- }
- }
- }
- `;
-
- const data = await linearGraphQL(apiKey, query) as {
- viewer: { id: string; name: string };
- teams: { nodes: Array<{ id: string; name: string; key: string }> };
- };
-
- // Get issue count for the first team
- let issueCount = 0;
- let teamName: string | undefined;
-
- if (data.teams.nodes.length > 0) {
- teamName = data.teams.nodes[0].name;
- const countQuery = `
- query($teamId: String!) {
- team(id: $teamId) {
- issues {
- totalCount: nodes { id }
- }
- }
- }
- `;
- // Get approximate count
- const issuesQuery = `
- query($teamId: String!) {
- issues(filter: { team: { id: { eq: $teamId } } }, first: 0) {
- pageInfo {
- hasNextPage
- }
- }
- }
- `;
-
- // Simple count estimation - get first 250 issues
- const countData = await linearGraphQL(apiKey, `
- query($teamId: String!) {
- issues(filter: { team: { id: { eq: $teamId } } }, first: 250) {
- nodes { id }
- }
- }
- `, { teamId: data.teams.nodes[0].id }) as {
- issues: { nodes: Array<{ id: string }> };
- };
- issueCount = countData.issues.nodes.length;
- }
-
- return {
- success: true,
- data: {
- connected: true,
- teamName,
- issueCount,
- lastSyncedAt: new Date().toISOString()
- }
- };
- } catch (error) {
- return {
- success: true,
- data: {
- connected: false,
- error: error instanceof Error ? error.message : 'Failed to connect to Linear'
- }
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.LINEAR_GET_TEAMS,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const apiKey = getLinearApiKey(project);
- if (!apiKey) {
- return { success: false, error: 'No Linear API key configured' };
- }
-
- try {
- const query = `
- query {
- teams {
- nodes {
- id
- name
- key
- }
- }
- }
- `;
-
- const data = await linearGraphQL(apiKey, query) as {
- teams: { nodes: LinearTeam[] };
- };
-
- return { success: true, data: data.teams.nodes };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to fetch teams'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.LINEAR_GET_PROJECTS,
- async (_, projectId: string, teamId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const apiKey = getLinearApiKey(project);
- if (!apiKey) {
- return { success: false, error: 'No Linear API key configured' };
- }
-
- try {
- const query = `
- query($teamId: String!) {
- team(id: $teamId) {
- projects {
- nodes {
- id
- name
- state
- }
- }
- }
- }
- `;
-
- const data = await linearGraphQL(apiKey, query, { teamId }) as {
- team: { projects: { nodes: LinearProject[] } };
- };
-
- return { success: true, data: data.team.projects.nodes };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to fetch projects'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.LINEAR_GET_ISSUES,
- async (_, projectId: string, teamId?: string, linearProjectId?: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const apiKey = getLinearApiKey(project);
- if (!apiKey) {
- return { success: false, error: 'No Linear API key configured' };
- }
-
- try {
- // Build filter based on provided parameters
- const filters: string[] = [];
- if (teamId) {
- filters.push(`team: { id: { eq: "${teamId}" } }`);
- }
- if (linearProjectId) {
- filters.push(`project: { id: { eq: "${linearProjectId}" } }`);
- }
-
- const filterClause = filters.length > 0 ? `filter: { ${filters.join(', ')} }` : '';
-
- const query = `
- query {
- issues(${filterClause}, first: 250, orderBy: updatedAt) {
- nodes {
- id
- identifier
- title
- description
- state {
- id
- name
- type
- }
- priority
- priorityLabel
- labels {
- nodes {
- id
- name
- color
- }
- }
- assignee {
- id
- name
- email
- }
- project {
- id
- name
- }
- createdAt
- updatedAt
- url
- }
- }
- }
- `;
-
- const data = await linearGraphQL(apiKey, query) as {
- issues: {
- nodes: Array<{
- id: string;
- identifier: string;
- title: string;
- description?: string;
- state: { id: string; name: string; type: string };
- priority: number;
- priorityLabel: string;
- labels: { nodes: Array<{ id: string; name: string; color: string }> };
- assignee?: { id: string; name: string; email: string };
- project?: { id: string; name: string };
- createdAt: string;
- updatedAt: string;
- url: string;
- }>;
- };
- };
-
- // Transform to our LinearIssue format
- const issues: LinearIssue[] = data.issues.nodes.map(issue => ({
- ...issue,
- labels: issue.labels.nodes
- }));
-
- return { success: true, data: issues };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to fetch issues'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.LINEAR_IMPORT_ISSUES,
- async (_, projectId: string, issueIds: string[]): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const apiKey = getLinearApiKey(project);
- if (!apiKey) {
- return { success: false, error: 'No Linear API key configured' };
- }
-
- try {
- // First, fetch the full details of selected issues
- const query = `
- query($ids: [String!]!) {
- issues(filter: { id: { in: $ids } }) {
- nodes {
- id
- identifier
- title
- description
- state {
- id
- name
- type
- }
- priority
- priorityLabel
- labels {
- nodes {
- id
- name
- color
- }
- }
- url
- }
- }
- }
- `;
-
- const data = await linearGraphQL(apiKey, query, { ids: issueIds }) as {
- issues: {
- nodes: Array<{
- id: string;
- identifier: string;
- title: string;
- description?: string;
- state: { id: string; name: string; type: string };
- priority: number;
- priorityLabel: string;
- labels: { nodes: Array<{ id: string; name: string; color: string }> };
- url: string;
- }>;
- };
- };
-
- let imported = 0;
- let failed = 0;
- const errors: string[] = [];
-
- // Set up specs directory
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specsDir = path.join(project.path, specsBaseDir);
- if (!existsSync(specsDir)) {
- mkdirSync(specsDir, { recursive: true });
- }
-
- // Create tasks for each imported issue
- for (const issue of data.issues.nodes) {
- try {
- // Build description from Linear issue
- const labels = issue.labels.nodes.map(l => l.name).join(', ');
- const description = `# ${issue.title}
-
-**Linear Issue:** [${issue.identifier}](${issue.url})
-**Priority:** ${issue.priorityLabel}
-**Status:** ${issue.state.name}
-${labels ? `**Labels:** ${labels}` : ''}
-
-## Description
-
-${issue.description || 'No description provided.'}
-`;
-
- // Find next available spec number
- let specNumber = 1;
- const existingDirs = readdirSync(specsDir, { withFileTypes: true })
- .filter(d => d.isDirectory())
- .map(d => d.name);
- const existingNumbers = existingDirs
- .map(name => {
- const match = name.match(/^(\d+)/);
- return match ? parseInt(match[1], 10) : 0;
- })
- .filter(n => n > 0);
- if (existingNumbers.length > 0) {
- specNumber = Math.max(...existingNumbers) + 1;
- }
-
- // Create spec ID with zero-padded number and slugified title
- const slugifiedTitle = issue.title
- .toLowerCase()
- .replace(/[^a-z0-9]+/g, '-')
- .replace(/^-|-$/g, '')
- .substring(0, 50);
- const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`;
-
- // Create spec directory
- const specDir = path.join(specsDir, specId);
- mkdirSync(specDir, { recursive: true });
-
- // Create initial implementation_plan.json
- const now = new Date().toISOString();
- const implementationPlan = {
- feature: issue.title,
- description: description,
- created_at: now,
- updated_at: now,
- status: 'pending',
- phases: []
- };
- writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN), JSON.stringify(implementationPlan, null, 2));
-
- // Create requirements.json
- const requirements = {
- task_description: description,
- workflow_type: 'feature'
- };
- writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS), JSON.stringify(requirements, null, 2));
-
- // Build metadata
- const metadata: TaskMetadata = {
- sourceType: 'linear',
- linearIssueId: issue.id,
- linearIdentifier: issue.identifier,
- linearUrl: issue.url,
- category: 'feature'
- };
- writeFileSync(path.join(specDir, 'task_metadata.json'), JSON.stringify(metadata, null, 2));
-
- // Start spec creation with the existing spec directory
- agentManager.startSpecCreation(specId, project.path, description, specDir, metadata);
-
- imported++;
- } catch (err) {
- failed++;
- errors.push(`Failed to import ${issue.identifier}: ${err instanceof Error ? err.message : 'Unknown error'}`);
- }
- }
-
- return {
- success: true,
- data: {
- success: failed === 0,
- imported,
- failed,
- errors: errors.length > 0 ? errors : undefined
- }
- };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to import issues'
- };
- }
- }
- );
-
- // ============================================
- // GitHub Integration Operations
- // ============================================
-
- /**
- * Helper to get GitHub config from project env
- */
- const getGitHubConfig = (project: Project): { token: string; repo: string } | null => {
- if (!project.autoBuildPath) return null;
- const envPath = path.join(project.path, project.autoBuildPath, '.env');
- if (!existsSync(envPath)) return null;
-
- try {
- const content = readFileSync(envPath, 'utf-8');
- const vars = parseEnvFile(content);
- const token = vars['GITHUB_TOKEN'];
- const repo = vars['GITHUB_REPO'];
-
- if (!token || !repo) return null;
- return { token, repo };
- } catch {
- return null;
- }
- };
-
- /**
- * Make a request to the GitHub API
- */
- const githubFetch = async (
- token: string,
- endpoint: string,
- options: RequestInit = {}
- ): Promise => {
- const url = endpoint.startsWith('http')
- ? endpoint
- : `https://api.github.com${endpoint}`;
-
- const response = await fetch(url, {
- ...options,
- headers: {
- 'Accept': 'application/vnd.github.v3+json',
- 'Authorization': `Bearer ${token}`,
- 'User-Agent': 'Auto-Claude-UI',
- ...options.headers
- }
- });
-
- if (!response.ok) {
- const errorBody = await response.text();
- throw new Error(`GitHub API error: ${response.status} ${response.statusText} - ${errorBody}`);
- }
-
- return response.json();
- };
-
- ipcMain.handle(
- IPC_CHANNELS.GITHUB_CHECK_CONNECTION,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const config = getGitHubConfig(project);
- if (!config) {
- return {
- success: true,
- data: {
- connected: false,
- error: 'No GitHub token or repository configured'
- }
- };
- }
-
- try {
- // Fetch repo info
- const repoData = await githubFetch(
- config.token,
- `/repos/${config.repo}`
- ) as { full_name: string; description?: string };
-
- // Count open issues
- const issuesData = await githubFetch(
- config.token,
- `/repos/${config.repo}/issues?state=open&per_page=1`
- ) as unknown[];
-
- const openCount = Array.isArray(issuesData) ? issuesData.length : 0;
-
- return {
- success: true,
- data: {
- connected: true,
- repoFullName: repoData.full_name,
- repoDescription: repoData.description,
- issueCount: openCount,
- lastSyncedAt: new Date().toISOString()
- }
- };
- } catch (error) {
- return {
- success: true,
- data: {
- connected: false,
- error: error instanceof Error ? error.message : 'Failed to connect to GitHub'
- }
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.GITHUB_GET_REPOSITORIES,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const config = getGitHubConfig(project);
- if (!config) {
- return { success: false, error: 'No GitHub token configured' };
- }
-
- try {
- const repos = await githubFetch(
- config.token,
- '/user/repos?per_page=100&sort=updated'
- ) as Array<{
- id: number;
- name: string;
- full_name: string;
- description?: string;
- html_url: string;
- default_branch: string;
- private: boolean;
- owner: { login: string; avatar_url?: string };
- }>;
-
- const result: GitHubRepository[] = repos.map(repo => ({
- id: repo.id,
- name: repo.name,
- fullName: repo.full_name,
- description: repo.description,
- url: repo.html_url,
- defaultBranch: repo.default_branch,
- private: repo.private,
- owner: {
- login: repo.owner.login,
- avatarUrl: repo.owner.avatar_url
- }
- }));
-
- return { success: true, data: result };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to fetch repositories'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.GITHUB_GET_ISSUES,
- async (_, projectId: string, state: 'open' | 'closed' | 'all' = 'open'): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const config = getGitHubConfig(project);
- if (!config) {
- return { success: false, error: 'No GitHub token or repository configured' };
- }
-
- try {
- const issues = await githubFetch(
- config.token,
- `/repos/${config.repo}/issues?state=${state}&per_page=100&sort=updated`
- ) as Array<{
- id: number;
- number: number;
- title: string;
- body?: string;
- state: 'open' | 'closed';
- labels: Array<{ id: number; name: string; color: string; description?: string }>;
- assignees: Array<{ login: string; avatar_url?: string }>;
- user: { login: string; avatar_url?: string };
- milestone?: { id: number; title: string; state: 'open' | 'closed' };
- created_at: string;
- updated_at: string;
- closed_at?: string;
- comments: number;
- url: string;
- html_url: string;
- pull_request?: unknown;
- }>;
-
- // Filter out pull requests
- const issuesOnly = issues.filter(issue => !issue.pull_request);
-
- const result: GitHubIssue[] = issuesOnly.map(issue => ({
- id: issue.id,
- number: issue.number,
- title: issue.title,
- body: issue.body,
- state: issue.state,
- labels: issue.labels,
- assignees: issue.assignees.map(a => ({
- login: a.login,
- avatarUrl: a.avatar_url
- })),
- author: {
- login: issue.user.login,
- avatarUrl: issue.user.avatar_url
- },
- milestone: issue.milestone,
- createdAt: issue.created_at,
- updatedAt: issue.updated_at,
- closedAt: issue.closed_at,
- commentsCount: issue.comments,
- url: issue.url,
- htmlUrl: issue.html_url,
- repoFullName: config.repo
- }));
-
- return { success: true, data: result };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to fetch issues'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.GITHUB_GET_ISSUE,
- async (_, projectId: string, issueNumber: number): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const config = getGitHubConfig(project);
- if (!config) {
- return { success: false, error: 'No GitHub token or repository configured' };
- }
-
- try {
- const issue = await githubFetch(
- config.token,
- `/repos/${config.repo}/issues/${issueNumber}`
- ) as {
- id: number;
- number: number;
- title: string;
- body?: string;
- state: 'open' | 'closed';
- labels: Array<{ id: number; name: string; color: string; description?: string }>;
- assignees: Array<{ login: string; avatar_url?: string }>;
- user: { login: string; avatar_url?: string };
- milestone?: { id: number; title: string; state: 'open' | 'closed' };
- created_at: string;
- updated_at: string;
- closed_at?: string;
- comments: number;
- url: string;
- html_url: string;
- };
-
- const result: GitHubIssue = {
- id: issue.id,
- number: issue.number,
- title: issue.title,
- body: issue.body,
- state: issue.state,
- labels: issue.labels,
- assignees: issue.assignees.map(a => ({
- login: a.login,
- avatarUrl: a.avatar_url
- })),
- author: {
- login: issue.user.login,
- avatarUrl: issue.user.avatar_url
- },
- milestone: issue.milestone,
- createdAt: issue.created_at,
- updatedAt: issue.updated_at,
- closedAt: issue.closed_at,
- commentsCount: issue.comments,
- url: issue.url,
- htmlUrl: issue.html_url,
- repoFullName: config.repo
- };
-
- return { success: true, data: result };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to fetch issue'
- };
- }
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.GITHUB_INVESTIGATE_ISSUE,
- async (_, projectId: string, issueNumber: number) => {
- const mainWindow = getMainWindow();
- if (!mainWindow) return;
-
- const project = projectStore.getProject(projectId);
- if (!project) {
- mainWindow.webContents.send(
- IPC_CHANNELS.GITHUB_INVESTIGATION_ERROR,
- projectId,
- 'Project not found'
- );
- return;
- }
-
- const config = getGitHubConfig(project);
- if (!config) {
- mainWindow.webContents.send(
- IPC_CHANNELS.GITHUB_INVESTIGATION_ERROR,
- projectId,
- 'No GitHub token or repository configured'
- );
- return;
- }
-
- try {
- // Send progress update: fetching issue
- mainWindow.webContents.send(
- IPC_CHANNELS.GITHUB_INVESTIGATION_PROGRESS,
- projectId,
- {
- phase: 'fetching',
- issueNumber,
- progress: 10,
- message: 'Fetching issue details...'
- } as GitHubInvestigationStatus
- );
-
- // Fetch the issue
- const issue = await githubFetch(
- config.token,
- `/repos/${config.repo}/issues/${issueNumber}`
- ) as {
- number: number;
- title: string;
- body?: string;
- labels: Array<{ name: string }>;
- html_url: string;
- };
-
- // Fetch issue comments for more context
- const comments = await githubFetch(
- config.token,
- `/repos/${config.repo}/issues/${issueNumber}/comments`
- ) as Array<{ body: string; user: { login: string } }>;
-
- // Build context for the AI investigation
- const issueContext = `
-# GitHub Issue #${issue.number}: ${issue.title}
-
-${issue.body || 'No description provided.'}
-
-${comments.length > 0 ? `## Comments (${comments.length}):
-${comments.map(c => `**${c.user.login}:** ${c.body}`).join('\n\n')}` : ''}
-
-**Labels:** ${issue.labels.map(l => l.name).join(', ') || 'None'}
-**URL:** ${issue.html_url}
-`;
-
- // Send progress update: analyzing
- mainWindow.webContents.send(
- IPC_CHANNELS.GITHUB_INVESTIGATION_PROGRESS,
- projectId,
- {
- phase: 'analyzing',
- issueNumber,
- progress: 30,
- message: 'AI is analyzing the issue...'
- } as GitHubInvestigationStatus
- );
-
- // Build task description
- const taskDescription = `Investigate GitHub Issue #${issue.number}: ${issue.title}
-
-${issueContext}
-
-Please analyze this issue and provide:
-1. A brief summary of what the issue is about
-2. A proposed solution approach
-3. The files that would likely need to be modified
-4. Estimated complexity (simple/standard/complex)
-5. Acceptance criteria for resolving this issue`;
-
- // Create proper spec directory
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specsDir = path.join(project.path, specsBaseDir);
- if (!existsSync(specsDir)) {
- mkdirSync(specsDir, { recursive: true });
- }
-
- // Find next available spec number
- let specNumber = 1;
- const existingDirs = readdirSync(specsDir, { withFileTypes: true })
- .filter(d => d.isDirectory())
- .map(d => d.name);
- const existingNumbers = existingDirs
- .map(name => {
- const match = name.match(/^(\d+)/);
- return match ? parseInt(match[1], 10) : 0;
- })
- .filter(n => n > 0);
- if (existingNumbers.length > 0) {
- specNumber = Math.max(...existingNumbers) + 1;
- }
-
- // Create spec ID with zero-padded number and slugified title
- const slugifiedTitle = issue.title
- .toLowerCase()
- .replace(/[^a-z0-9]+/g, '-')
- .replace(/^-|-$/g, '')
- .substring(0, 50);
- const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`;
-
- // Create spec directory
- const specDir = path.join(specsDir, specId);
- mkdirSync(specDir, { recursive: true });
-
- // Create initial implementation_plan.json
- const now = new Date().toISOString();
- const implementationPlan = {
- feature: issue.title,
- description: taskDescription,
- created_at: now,
- updated_at: now,
- status: 'pending',
- phases: []
- };
- writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN), JSON.stringify(implementationPlan, null, 2));
-
- // Create requirements.json
- const requirements = {
- task_description: taskDescription,
- workflow_type: 'feature'
- };
- writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS), JSON.stringify(requirements, null, 2));
-
- // Build metadata
- const metadata: TaskMetadata = {
- sourceType: 'github',
- githubIssueNumber: issue.number,
- githubUrl: issue.html_url,
- category: 'feature'
- };
- writeFileSync(path.join(specDir, 'task_metadata.json'), JSON.stringify(metadata, null, 2));
-
- // Start spec creation with the existing spec directory
- agentManager.startSpecCreation(specId, project.path, taskDescription, specDir, metadata);
-
- // Send progress update: creating task
- mainWindow.webContents.send(
- IPC_CHANNELS.GITHUB_INVESTIGATION_PROGRESS,
- projectId,
- {
- phase: 'creating_task',
- issueNumber,
- progress: 70,
- message: 'Creating task from investigation...'
- } as GitHubInvestigationStatus
- );
-
- const investigationResult: GitHubInvestigationResult = {
- success: true,
- issueNumber,
- analysis: {
- summary: `Investigation of issue #${issueNumber}: ${issue.title}`,
- proposedSolution: 'Task has been created for AI agent to implement the solution.',
- affectedFiles: [],
- estimatedComplexity: 'standard',
- acceptanceCriteria: [
- `Issue #${issueNumber} requirements are met`,
- 'All existing tests pass',
- 'New functionality is tested'
- ]
- },
- taskId: specId
- };
-
- // Send completion
- mainWindow.webContents.send(
- IPC_CHANNELS.GITHUB_INVESTIGATION_PROGRESS,
- projectId,
- {
- phase: 'complete',
- issueNumber,
- progress: 100,
- message: 'Investigation complete!'
- } as GitHubInvestigationStatus
- );
-
- mainWindow.webContents.send(
- IPC_CHANNELS.GITHUB_INVESTIGATION_COMPLETE,
- projectId,
- investigationResult
- );
-
- } catch (error) {
- mainWindow.webContents.send(
- IPC_CHANNELS.GITHUB_INVESTIGATION_ERROR,
- projectId,
- error instanceof Error ? error.message : 'Failed to investigate issue'
- );
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.GITHUB_IMPORT_ISSUES,
- async (_, projectId: string, issueNumbers: number[]): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const config = getGitHubConfig(project);
- if (!config) {
- return { success: false, error: 'No GitHub token or repository configured' };
- }
-
- let imported = 0;
- let failed = 0;
- const errors: string[] = [];
- const tasks: Task[] = [];
-
- // Set up specs directory
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specsDir = path.join(project.path, specsBaseDir);
- if (!existsSync(specsDir)) {
- mkdirSync(specsDir, { recursive: true });
- }
-
- for (const issueNumber of issueNumbers) {
- try {
- const issue = await githubFetch(
- config.token,
- `/repos/${config.repo}/issues/${issueNumber}`
- ) as {
- number: number;
- title: string;
- body?: string;
- labels: Array<{ name: string }>;
- html_url: string;
- };
-
- const labels = issue.labels.map(l => l.name).join(', ');
- const description = `# ${issue.title}
-
-**GitHub Issue:** [#${issue.number}](${issue.html_url})
-${labels ? `**Labels:** ${labels}` : ''}
-
-## Description
-
-${issue.body || 'No description provided.'}
-`;
-
- // Find next available spec number
- let specNumber = 1;
- const existingDirs = readdirSync(specsDir, { withFileTypes: true })
- .filter(d => d.isDirectory())
- .map(d => d.name);
- const existingNumbers = existingDirs
- .map(name => {
- const match = name.match(/^(\d+)/);
- return match ? parseInt(match[1], 10) : 0;
- })
- .filter(n => n > 0);
- if (existingNumbers.length > 0) {
- specNumber = Math.max(...existingNumbers) + 1;
- }
-
- // Create spec ID with zero-padded number and slugified title
- const slugifiedTitle = issue.title
- .toLowerCase()
- .replace(/[^a-z0-9]+/g, '-')
- .replace(/^-|-$/g, '')
- .substring(0, 50);
- const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`;
-
- // Create spec directory
- const specDir = path.join(specsDir, specId);
- mkdirSync(specDir, { recursive: true });
-
- // Create initial implementation_plan.json
- const now = new Date().toISOString();
- const implementationPlan = {
- feature: issue.title,
- description: description,
- created_at: now,
- updated_at: now,
- status: 'pending',
- phases: []
- };
- writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN), JSON.stringify(implementationPlan, null, 2));
-
- // Create requirements.json
- const requirements = {
- task_description: description,
- workflow_type: 'feature'
- };
- writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS), JSON.stringify(requirements, null, 2));
-
- // Build metadata
- const metadata: TaskMetadata = {
- sourceType: 'github',
- githubIssueNumber: issue.number,
- githubUrl: issue.html_url,
- category: 'feature'
- };
- writeFileSync(path.join(specDir, 'task_metadata.json'), JSON.stringify(metadata, null, 2));
-
- // Start spec creation with the existing spec directory
- agentManager.startSpecCreation(specId, project.path, description, specDir, metadata);
- imported++;
- } catch (err) {
- failed++;
- errors.push(`Failed to import #${issueNumber}: ${err instanceof Error ? err.message : 'Unknown error'}`);
- }
- }
-
- return {
- success: true,
- data: {
- success: failed === 0,
- imported,
- failed,
- errors: errors.length > 0 ? errors : undefined,
- tasks
- }
- };
- }
- );
-
- /**
- * Create a GitHub release using the gh CLI
- */
- ipcMain.handle(
- IPC_CHANNELS.GITHUB_CREATE_RELEASE,
- async (
- _,
- projectId: string,
- version: string,
- releaseNotes: string,
- options?: { draft?: boolean; prerelease?: boolean }
- ): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- try {
- // Check if gh CLI is available
- // Use 'where' on Windows, 'which' on Unix
- try {
- const checkCmd = process.platform === 'win32' ? 'where gh' : 'which gh';
- execSync(checkCmd, { encoding: 'utf-8', stdio: 'pipe' });
- } catch {
- return {
- success: false,
- error: 'GitHub CLI (gh) not found. Please install it: https://cli.github.com/'
- };
- }
-
- // Check if user is authenticated
- try {
- execSync('gh auth status', { cwd: project.path, encoding: 'utf-8', stdio: 'pipe' });
- } catch {
- return {
- success: false,
- error: 'Not authenticated with GitHub. Run "gh auth login" in terminal first.'
- };
- }
-
- // Prepare tag name (ensure v prefix)
- const tag = version.startsWith('v') ? version : `v${version}`;
-
- // Build gh release command
- const args = ['release', 'create', tag, '--title', tag, '--notes', releaseNotes];
- if (options?.draft) args.push('--draft');
- if (options?.prerelease) args.push('--prerelease');
-
- // Create the release
- const output = execSync(`gh ${args.map(a => `"${a.replace(/"/g, '\\"')}"`).join(' ')}`, {
- cwd: project.path,
- encoding: 'utf-8',
- stdio: 'pipe'
- }).trim();
-
- // Output is typically the release URL
- const releaseUrl = output || `https://github.com/releases/tag/${tag}`;
-
- return {
- success: true,
- data: { url: releaseUrl }
- };
- } catch (error) {
- const errorMsg = error instanceof Error ? error.message : 'Failed to create release';
- // Try to extract more useful error message from stderr
- if (error && typeof error === 'object' && 'stderr' in error) {
- return { success: false, error: String(error.stderr) || errorMsg };
- }
- return { success: false, error: errorMsg };
- }
- }
- );
-
- // ============================================
- // Auto Claude Source Update Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.AUTOBUILD_SOURCE_CHECK,
- async (): Promise> => {
- try {
- const result = await checkSourceUpdates();
- return { success: true, data: result };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to check for updates'
- };
- }
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.AUTOBUILD_SOURCE_DOWNLOAD,
- () => {
- const mainWindow = getMainWindow();
- if (!mainWindow) return;
-
- // Start download in background
- downloadAndApplyUpdate((progress) => {
- mainWindow.webContents.send(
- IPC_CHANNELS.AUTOBUILD_SOURCE_PROGRESS,
- progress
- );
- }).then((result) => {
- if (result.success) {
- mainWindow.webContents.send(
- IPC_CHANNELS.AUTOBUILD_SOURCE_PROGRESS,
- {
- stage: 'complete',
- message: `Updated to version ${result.version}`
- } as AutoBuildSourceUpdateProgress
- );
- } else {
- mainWindow.webContents.send(
- IPC_CHANNELS.AUTOBUILD_SOURCE_PROGRESS,
- {
- stage: 'error',
- message: result.error || 'Update failed'
- } as AutoBuildSourceUpdateProgress
- );
- }
- }).catch((error) => {
- mainWindow.webContents.send(
- IPC_CHANNELS.AUTOBUILD_SOURCE_PROGRESS,
- {
- stage: 'error',
- message: error instanceof Error ? error.message : 'Update failed'
- } as AutoBuildSourceUpdateProgress
- );
- });
-
- // Send initial progress
- mainWindow.webContents.send(
- IPC_CHANNELS.AUTOBUILD_SOURCE_PROGRESS,
- {
- stage: 'checking',
- message: 'Starting update...'
- } as AutoBuildSourceUpdateProgress
- );
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.AUTOBUILD_SOURCE_VERSION,
- async (): Promise> => {
- try {
- const version = getBundledVersion();
- return { success: true, data: version };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get version'
- };
- }
- }
- );
-
- // ============================================
- // Auto Claude Source Environment Operations
- // ============================================
-
- /**
- * Parse an .env file content into a key-value object
- */
- const parseSourceEnvFile = (content: string): Record => {
- const vars: Record = {};
- for (const line of content.split('\n')) {
- const trimmed = line.trim();
- if (!trimmed || trimmed.startsWith('#')) continue;
-
- const eqIndex = trimmed.indexOf('=');
- if (eqIndex > 0) {
- const key = trimmed.substring(0, eqIndex).trim();
- let value = trimmed.substring(eqIndex + 1).trim();
- // Remove quotes if present
- if ((value.startsWith('"') && value.endsWith('"')) ||
- (value.startsWith("'") && value.endsWith("'"))) {
- value = value.slice(1, -1);
- }
- vars[key] = value;
- }
- }
- return vars;
- };
-
- ipcMain.handle(
- IPC_CHANNELS.AUTOBUILD_SOURCE_ENV_GET,
- async (): Promise> => {
- try {
- const sourcePath = getEffectiveSourcePath();
- if (!sourcePath) {
- return {
- success: true,
- data: {
- hasClaudeToken: false,
- envExists: false,
- sourcePath: undefined
- }
- };
- }
-
- const envPath = path.join(sourcePath, '.env');
- const envExists = existsSync(envPath);
-
- if (!envExists) {
- return {
- success: true,
- data: {
- hasClaudeToken: false,
- envExists: false,
- sourcePath
- }
- };
- }
-
- const content = readFileSync(envPath, 'utf-8');
- const vars = parseSourceEnvFile(content);
- const hasToken = !!vars['CLAUDE_CODE_OAUTH_TOKEN'];
-
- return {
- success: true,
- data: {
- hasClaudeToken: hasToken,
- claudeOAuthToken: hasToken ? vars['CLAUDE_CODE_OAUTH_TOKEN'] : undefined,
- envExists: true,
- sourcePath
- }
- };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get source env'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.AUTOBUILD_SOURCE_ENV_UPDATE,
- async (_, config: { claudeOAuthToken?: string }): Promise => {
- try {
- const sourcePath = getEffectiveSourcePath();
- if (!sourcePath) {
- return {
- success: false,
- error: 'Auto-Claude source path not found. Please configure it in App Settings.'
- };
- }
-
- const envPath = path.join(sourcePath, '.env');
-
- // Read existing content or start fresh
- let existingContent = '';
- const existingVars: Record = {};
-
- if (existsSync(envPath)) {
- existingContent = readFileSync(envPath, 'utf-8');
- Object.assign(existingVars, parseSourceEnvFile(existingContent));
- }
-
- // Update the token
- if (config.claudeOAuthToken !== undefined) {
- existingVars['CLAUDE_CODE_OAUTH_TOKEN'] = config.claudeOAuthToken;
- }
-
- // Rebuild the .env file preserving comments and structure
- const lines = existingContent.split('\n');
- const processedKeys = new Set();
- const outputLines: string[] = [];
-
- for (const line of lines) {
- const trimmed = line.trim();
- if (!trimmed || trimmed.startsWith('#')) {
- outputLines.push(line);
- continue;
- }
-
- const eqIndex = trimmed.indexOf('=');
- if (eqIndex > 0) {
- const key = trimmed.substring(0, eqIndex).trim();
- if (key in existingVars) {
- outputLines.push(`${key}=${existingVars[key]}`);
- processedKeys.add(key);
- } else {
- outputLines.push(line);
- }
- } else {
- outputLines.push(line);
- }
- }
-
- // Add any new keys that weren't in the original file
- for (const [key, value] of Object.entries(existingVars)) {
- if (!processedKeys.has(key)) {
- outputLines.push(`${key}=${value}`);
- }
- }
-
- writeFileSync(envPath, outputLines.join('\n'));
-
- return { success: true };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to update source env'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.AUTOBUILD_SOURCE_ENV_CHECK_TOKEN,
- async (): Promise> => {
- try {
- const sourcePath = getEffectiveSourcePath();
- if (!sourcePath) {
- return {
- success: true,
- data: {
- hasToken: false,
- sourcePath: undefined,
- error: 'Auto-Claude source path not found'
- }
- };
- }
-
- const envPath = path.join(sourcePath, '.env');
- if (!existsSync(envPath)) {
- return {
- success: true,
- data: {
- hasToken: false,
- sourcePath,
- error: '.env file does not exist'
- }
- };
- }
-
- const content = readFileSync(envPath, 'utf-8');
- const vars = parseSourceEnvFile(content);
- const hasToken = !!vars['CLAUDE_CODE_OAUTH_TOKEN'] && vars['CLAUDE_CODE_OAUTH_TOKEN'].length > 0;
-
- return {
- success: true,
- data: {
- hasToken,
- sourcePath
- }
- };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to check source token'
- };
- }
- }
- );
-
- // ============================================
- // Ideation Operations
- // ============================================
-
- /**
- * Transform an idea from snake_case (Python backend) to camelCase (TypeScript frontend)
- */
- const transformIdeaFromSnakeCase = (idea: Record) => {
- const base = {
- id: idea.id as string,
- type: idea.type as string,
- title: idea.title as string,
- description: idea.description as string,
- rationale: idea.rationale as string,
- status: idea.status as string || 'draft',
- createdAt: idea.created_at ? new Date(idea.created_at as string) : new Date()
- };
-
- if (idea.type === 'code_improvements') {
- return {
- ...base,
- buildsUpon: idea.builds_upon || idea.buildsUpon || [],
- estimatedEffort: idea.estimated_effort || idea.estimatedEffort || 'small',
- affectedFiles: idea.affected_files || idea.affectedFiles || [],
- existingPatterns: idea.existing_patterns || idea.existingPatterns || [],
- implementationApproach: idea.implementation_approach || idea.implementationApproach || ''
- };
- } else if (idea.type === 'ui_ux_improvements') {
- return {
- ...base,
- category: idea.category || 'usability',
- affectedComponents: idea.affected_components || idea.affectedComponents || [],
- screenshots: idea.screenshots || [],
- currentState: idea.current_state || idea.currentState || '',
- proposedChange: idea.proposed_change || idea.proposedChange || '',
- userBenefit: idea.user_benefit || idea.userBenefit || ''
- };
- } else if (idea.type === 'documentation_gaps') {
- return {
- ...base,
- category: idea.category || 'readme',
- targetAudience: idea.target_audience || idea.targetAudience || 'developers',
- affectedAreas: idea.affected_areas || idea.affectedAreas || [],
- currentDocumentation: idea.current_documentation || idea.currentDocumentation || '',
- proposedContent: idea.proposed_content || idea.proposedContent || '',
- priority: idea.priority || 'medium',
- estimatedEffort: idea.estimated_effort || idea.estimatedEffort || 'small'
- };
- } else if (idea.type === 'security_hardening') {
- return {
- ...base,
- category: idea.category || 'configuration',
- severity: idea.severity || 'medium',
- affectedFiles: idea.affected_files || idea.affectedFiles || [],
- vulnerability: idea.vulnerability || '',
- currentRisk: idea.current_risk || idea.currentRisk || '',
- remediation: idea.remediation || '',
- references: idea.references || [],
- compliance: idea.compliance || []
- };
- } else if (idea.type === 'performance_optimizations') {
- return {
- ...base,
- category: idea.category || 'runtime',
- impact: idea.impact || 'medium',
- affectedAreas: idea.affected_areas || idea.affectedAreas || [],
- currentMetric: idea.current_metric || idea.currentMetric || '',
- expectedImprovement: idea.expected_improvement || idea.expectedImprovement || '',
- implementation: idea.implementation || '',
- tradeoffs: idea.tradeoffs || '',
- estimatedEffort: idea.estimated_effort || idea.estimatedEffort || 'medium'
- };
- } else if (idea.type === 'code_quality') {
- return {
- ...base,
- category: idea.category || 'code_smells',
- severity: idea.severity || 'minor',
- affectedFiles: idea.affected_files || idea.affectedFiles || [],
- currentState: idea.current_state || idea.currentState || '',
- proposedChange: idea.proposed_change || idea.proposedChange || '',
- codeExample: idea.code_example || idea.codeExample || '',
- bestPractice: idea.best_practice || idea.bestPractice || '',
- metrics: idea.metrics || {},
- estimatedEffort: idea.estimated_effort || idea.estimatedEffort || 'medium',
- breakingChange: idea.breaking_change ?? idea.breakingChange ?? false,
- prerequisites: idea.prerequisites || []
- };
- }
-
- return base;
- };
-
- ipcMain.handle(
- IPC_CHANNELS.IDEATION_GET,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const ideationPath = path.join(
- project.path,
- AUTO_BUILD_PATHS.IDEATION_DIR,
- AUTO_BUILD_PATHS.IDEATION_FILE
- );
-
- if (!existsSync(ideationPath)) {
- return { success: true, data: null };
- }
-
- try {
- const content = readFileSync(ideationPath, 'utf-8');
- const rawIdeation = JSON.parse(content);
-
- // Transform snake_case to camelCase for frontend
- const session: IdeationSession = {
- id: rawIdeation.id || `ideation-${Date.now()}`,
- projectId,
- config: {
- enabledTypes: rawIdeation.config?.enabled_types || rawIdeation.config?.enabledTypes || [],
- includeRoadmapContext: rawIdeation.config?.include_roadmap_context ?? rawIdeation.config?.includeRoadmapContext ?? true,
- includeKanbanContext: rawIdeation.config?.include_kanban_context ?? rawIdeation.config?.includeKanbanContext ?? true,
- maxIdeasPerType: rawIdeation.config?.max_ideas_per_type || rawIdeation.config?.maxIdeasPerType || 5
- },
- ideas: (rawIdeation.ideas || []).map((idea: Record) =>
- transformIdeaFromSnakeCase(idea)
- ),
- projectContext: {
- existingFeatures: rawIdeation.project_context?.existing_features || rawIdeation.projectContext?.existingFeatures || [],
- techStack: rawIdeation.project_context?.tech_stack || rawIdeation.projectContext?.techStack || [],
- targetAudience: rawIdeation.project_context?.target_audience || rawIdeation.projectContext?.targetAudience,
- plannedFeatures: rawIdeation.project_context?.planned_features || rawIdeation.projectContext?.plannedFeatures || []
- },
- generatedAt: rawIdeation.generated_at ? new Date(rawIdeation.generated_at) : new Date(),
- updatedAt: rawIdeation.updated_at ? new Date(rawIdeation.updated_at) : new Date()
- };
-
- return { success: true, data: session };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to read ideation'
- };
- }
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.IDEATION_GENERATE,
- (_, projectId: string, config: IdeationConfig) => {
- const mainWindow = getMainWindow();
- if (!mainWindow) return;
-
- const project = projectStore.getProject(projectId);
- if (!project) {
- mainWindow.webContents.send(
- IPC_CHANNELS.IDEATION_ERROR,
- projectId,
- 'Project not found'
- );
- return;
- }
-
- // Start ideation generation via agent manager
- agentManager.startIdeationGeneration(projectId, project.path, config, false);
-
- // Send initial progress
- mainWindow.webContents.send(
- IPC_CHANNELS.IDEATION_PROGRESS,
- projectId,
- {
- phase: 'analyzing',
- progress: 10,
- message: 'Analyzing project structure...'
- } as IdeationGenerationStatus
- );
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.IDEATION_REFRESH,
- (_, projectId: string, config: IdeationConfig) => {
- const mainWindow = getMainWindow();
- if (!mainWindow) return;
-
- const project = projectStore.getProject(projectId);
- if (!project) {
- mainWindow.webContents.send(
- IPC_CHANNELS.IDEATION_ERROR,
- projectId,
- 'Project not found'
- );
- return;
- }
-
- // Start ideation regeneration with refresh flag
- agentManager.startIdeationGeneration(projectId, project.path, config, true);
-
- // Send initial progress
- mainWindow.webContents.send(
- IPC_CHANNELS.IDEATION_PROGRESS,
- projectId,
- {
- phase: 'analyzing',
- progress: 10,
- message: 'Refreshing ideation...'
- } as IdeationGenerationStatus
- );
- }
- );
-
- // Stop ideation generation
- ipcMain.handle(
- IPC_CHANNELS.IDEATION_STOP,
- async (_, projectId: string): Promise => {
- const mainWindow = getMainWindow();
- const wasStopped = agentManager.stopIdeation(projectId);
-
- if (wasStopped && mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.IDEATION_STOPPED, projectId);
- }
-
- return { success: wasStopped };
- }
- );
-
- // Dismiss all ideas
- ipcMain.handle(
- IPC_CHANNELS.IDEATION_DISMISS_ALL,
- async (_, projectId: string): Promise => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const ideationPath = path.join(
- project.path,
- AUTO_BUILD_PATHS.IDEATION_DIR,
- AUTO_BUILD_PATHS.IDEATION_FILE
- );
-
- if (!existsSync(ideationPath)) {
- return { success: false, error: 'Ideation not found' };
- }
-
- try {
- const content = readFileSync(ideationPath, 'utf-8');
- const ideation = JSON.parse(content);
-
- // Dismiss all ideas that are not already dismissed or converted
- let dismissedCount = 0;
- ideation.ideas?.forEach((idea: { status: string }) => {
- if (idea.status !== 'dismissed' && idea.status !== 'converted') {
- idea.status = 'dismissed';
- dismissedCount++;
- }
- });
- ideation.updated_at = new Date().toISOString();
-
- writeFileSync(ideationPath, JSON.stringify(ideation, null, 2));
-
- return { success: true, data: { dismissedCount } };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to dismiss all ideas'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.IDEATION_UPDATE_IDEA,
- async (
- _,
- projectId: string,
- ideaId: string,
- status: IdeationStatus
- ): Promise => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const ideationPath = path.join(
- project.path,
- AUTO_BUILD_PATHS.IDEATION_DIR,
- AUTO_BUILD_PATHS.IDEATION_FILE
- );
-
- if (!existsSync(ideationPath)) {
- return { success: false, error: 'Ideation not found' };
- }
-
- try {
- const content = readFileSync(ideationPath, 'utf-8');
- const ideation = JSON.parse(content);
-
- // Find and update the idea
- const idea = ideation.ideas?.find((i: { id: string }) => i.id === ideaId);
- if (!idea) {
- return { success: false, error: 'Idea not found' };
- }
-
- idea.status = status;
- ideation.updated_at = new Date().toISOString();
-
- writeFileSync(ideationPath, JSON.stringify(ideation, null, 2));
-
- return { success: true };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to update idea'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.IDEATION_DISMISS,
- async (_, projectId: string, ideaId: string): Promise => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const ideationPath = path.join(
- project.path,
- AUTO_BUILD_PATHS.IDEATION_DIR,
- AUTO_BUILD_PATHS.IDEATION_FILE
- );
-
- if (!existsSync(ideationPath)) {
- return { success: false, error: 'Ideation not found' };
- }
-
- try {
- const content = readFileSync(ideationPath, 'utf-8');
- const ideation = JSON.parse(content);
-
- // Find and dismiss the idea
- const idea = ideation.ideas?.find((i: { id: string }) => i.id === ideaId);
- if (!idea) {
- return { success: false, error: 'Idea not found' };
- }
-
- idea.status = 'dismissed';
- ideation.updated_at = new Date().toISOString();
-
- writeFileSync(ideationPath, JSON.stringify(ideation, null, 2));
-
- return { success: true };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to dismiss idea'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.IDEATION_CONVERT_TO_TASK,
- async (_, projectId: string, ideaId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const ideationPath = path.join(
- project.path,
- AUTO_BUILD_PATHS.IDEATION_DIR,
- AUTO_BUILD_PATHS.IDEATION_FILE
- );
-
- if (!existsSync(ideationPath)) {
- return { success: false, error: 'Ideation not found' };
- }
-
- try {
- const content = readFileSync(ideationPath, 'utf-8');
- const ideation = JSON.parse(content);
-
- // Find the idea
- const idea = ideation.ideas?.find((i: { id: string }) => i.id === ideaId);
- if (!idea) {
- return { success: false, error: 'Idea not found' };
- }
-
- // Generate spec ID by finding next available number
- // Get specs directory path
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specsDir = path.join(project.path, specsBaseDir);
-
- // Ensure specs directory exists
- if (!existsSync(specsDir)) {
- mkdirSync(specsDir, { recursive: true });
- }
-
- // Find next spec number
- let nextNum = 1;
- try {
- const existingSpecs = readdirSync(specsDir, { withFileTypes: true })
- .filter(d => d.isDirectory())
- .map(d => {
- const match = d.name.match(/^(\d+)-/);
- return match ? parseInt(match[1], 10) : 0;
- })
- .filter(n => n > 0);
- if (existingSpecs.length > 0) {
- nextNum = Math.max(...existingSpecs) + 1;
- }
- } catch {
- // Use default 1
- }
-
- // Create spec directory name from idea title
- const slugifiedTitle = idea.title
- .toLowerCase()
- .replace(/[^a-z0-9]+/g, '-')
- .replace(/^-|-$/g, '')
- .substring(0, 50);
- const specId = `${String(nextNum).padStart(3, '0')}-${slugifiedTitle}`;
- const specDir = path.join(specsDir, specId);
-
- // Create the spec directory
- mkdirSync(specDir, { recursive: true });
-
- // Build task description based on idea type
- let taskDescription = `# ${idea.title}\n\n`;
- taskDescription += `${idea.description}\n\n`;
- taskDescription += `## Rationale\n${idea.rationale}\n\n`;
-
- // Note: high_value_features removed - strategic features belong to Roadmap
- // low_hanging_fruit renamed to code_improvements
- if (idea.type === 'code_improvements') {
- if (idea.builds_upon?.length) {
- taskDescription += `## Builds Upon\n${idea.builds_upon.map((b: string) => `- ${b}`).join('\n')}\n\n`;
- }
- if (idea.implementation_approach) {
- taskDescription += `## Implementation Approach\n${idea.implementation_approach}\n\n`;
- }
- if (idea.affected_files?.length) {
- taskDescription += `## Affected Files\n${idea.affected_files.map((f: string) => `- ${f}`).join('\n')}\n\n`;
- }
- if (idea.existing_patterns?.length) {
- taskDescription += `## Patterns to Follow\n${idea.existing_patterns.map((p: string) => `- ${p}`).join('\n')}\n\n`;
- }
- } else if (idea.type === 'ui_ux_improvements') {
- taskDescription += `## Category\n${idea.category}\n\n`;
- taskDescription += `## Current State\n${idea.current_state}\n\n`;
- taskDescription += `## Proposed Change\n${idea.proposed_change}\n\n`;
- taskDescription += `## User Benefit\n${idea.user_benefit}\n\n`;
- if (idea.affected_components?.length) {
- taskDescription += `## Affected Components\n${idea.affected_components.map((c: string) => `- ${c}`).join('\n')}\n\n`;
- }
- }
-
- // Create initial implementation_plan.json so task shows in kanban immediately
- const initialPlan: ImplementationPlan = {
- feature: idea.title,
- description: idea.description,
- created_at: new Date().toISOString(),
- updated_at: new Date().toISOString(),
- status: 'backlog',
- planStatus: 'pending',
- phases: [],
- workflow_type: 'development',
- services_involved: [],
- final_acceptance: [],
- spec_file: 'spec.md'
- };
- writeFileSync(
- path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN),
- JSON.stringify(initialPlan, null, 2)
- );
-
- // Create initial spec.md with the task description
- const specContent = `# ${idea.title}
-
-## Overview
-
-${idea.description}
-
-## Rationale
-
-${idea.rationale}
-
----
-*This spec was created from ideation and is pending detailed specification.*
-`;
- writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE), specContent);
-
- // Update idea with converted status
- idea.status = 'converted';
- idea.linked_task_id = specId;
- ideation.updated_at = new Date().toISOString();
- writeFileSync(ideationPath, JSON.stringify(ideation, null, 2));
-
- // Build metadata from idea type
- const metadata: TaskMetadata = {
- sourceType: 'ideation',
- ideationType: idea.type,
- ideaId: idea.id,
- rationale: idea.rationale
- };
-
- // Map idea type to task category
- // Note: high_value_features removed, low_hanging_fruit renamed to code_improvements
- const ideaTypeToCategory: Record = {
- 'code_improvements': 'feature',
- 'ui_ux_improvements': 'ui_ux',
- 'documentation_gaps': 'documentation',
- 'security_hardening': 'security',
- 'performance_optimizations': 'performance',
- 'code_quality': 'refactoring'
- };
- metadata.category = ideaTypeToCategory[idea.type] || 'feature';
-
- // Extract type-specific metadata
- // Note: high_value_features removed - strategic features belong to Roadmap
- // low_hanging_fruit renamed to code_improvements
- if (idea.type === 'code_improvements') {
- metadata.estimatedEffort = idea.estimated_effort;
- metadata.complexity = idea.estimated_effort; // trivial/small/medium/large/complex
- metadata.affectedFiles = idea.affected_files;
- } else if (idea.type === 'ui_ux_improvements') {
- metadata.uiuxCategory = idea.category;
- metadata.affectedFiles = idea.affected_components;
- metadata.problemSolved = idea.current_state;
- } else if (idea.type === 'documentation_gaps') {
- metadata.estimatedEffort = idea.estimated_effort;
- metadata.priority = idea.priority;
- metadata.targetAudience = idea.target_audience;
- metadata.affectedFiles = idea.affected_areas;
- } else if (idea.type === 'security_hardening') {
- metadata.securitySeverity = idea.severity;
- metadata.impact = idea.severity as TaskImpact; // Map severity to impact
- metadata.priority = idea.severity === 'critical' ? 'urgent' : idea.severity === 'high' ? 'high' : 'medium';
- metadata.affectedFiles = idea.affected_files;
- } else if (idea.type === 'performance_optimizations') {
- metadata.performanceCategory = idea.category;
- metadata.impact = idea.impact as TaskImpact;
- metadata.estimatedEffort = idea.estimated_effort;
- metadata.affectedFiles = idea.affected_areas;
- } else if (idea.type === 'code_quality') {
- metadata.codeQualitySeverity = idea.severity;
- metadata.estimatedEffort = idea.estimated_effort;
- metadata.affectedFiles = idea.affected_files;
- metadata.priority = idea.severity === 'critical' ? 'urgent' : idea.severity === 'major' ? 'high' : 'medium';
- }
-
- // Save metadata to a separate file for persistence
- const metadataPath = path.join(specDir, 'task_metadata.json');
- writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
-
- // Task is created in Planning (backlog) - user must manually start it
- // Previously auto-started spec creation here, but user should control when to start
-
- // Create task object to return
- const task: Task = {
- id: specId,
- specId: specId,
- projectId,
- title: idea.title,
- description: taskDescription,
- status: 'backlog',
- subtasks: [],
- logs: [],
- metadata,
- createdAt: new Date(),
- updatedAt: new Date()
- };
-
- return { success: true, data: task };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to convert idea to task'
- };
- }
- }
- );
-
- // ============================================
- // Ideation Agent Events → Renderer
- // ============================================
-
- agentManager.on('ideation-progress', (projectId: string, status: IdeationGenerationStatus) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.IDEATION_PROGRESS, projectId, status);
- }
- });
-
- agentManager.on('ideation-log', (projectId: string, log: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.IDEATION_LOG, projectId, log);
- }
- });
-
- agentManager.on('ideation-complete', (projectId: string, session: IdeationSession) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.IDEATION_COMPLETE, projectId, session);
- }
- });
-
- agentManager.on('ideation-error', (projectId: string, error: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.IDEATION_ERROR, projectId, error);
- }
- });
-
- agentManager.on('ideation-stopped', (projectId: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.IDEATION_STOPPED, projectId);
- }
- });
-
- // Handle streaming ideation type completion - load ideas for this type immediately
- agentManager.on('ideation-type-complete', (projectId: string, ideationType: string, ideasCount: number) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- // Read the type-specific ideas file and send to renderer
- const project = projectStore.getProject(projectId);
- if (project) {
- const typeFile = path.join(
- project.path,
- AUTO_BUILD_PATHS.IDEATION_DIR,
- `${ideationType}_ideas.json`
- );
- if (existsSync(typeFile)) {
- try {
- const content = readFileSync(typeFile, 'utf-8');
- const data = JSON.parse(content);
- const rawIdeas = data[ideationType] || [];
- // Transform ideas from snake_case to camelCase
- const ideas = rawIdeas.map((idea: Record) => transformIdeaFromSnakeCase(idea));
- mainWindow.webContents.send(
- IPC_CHANNELS.IDEATION_TYPE_COMPLETE,
- projectId,
- ideationType,
- ideas
- );
- } catch (err) {
- console.error(`[Ideation] Failed to read ${ideationType} ideas:`, err);
- }
- }
- }
- }
- });
-
- agentManager.on('ideation-type-failed', (projectId: string, ideationType: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.IDEATION_TYPE_FAILED, projectId, ideationType);
- }
- });
-
- // ============================================
- // Changelog Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.CHANGELOG_GET_DONE_TASKS,
- async (_, projectId: string, rendererTasks?: import('../shared/types').Task[]): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- // Use renderer tasks if provided (they have the correct UI status),
- // otherwise fall back to reading from filesystem
- const tasks = rendererTasks || projectStore.getTasks(projectId);
-
- // Get specs directory path
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const doneTasks = changelogService.getCompletedTasks(project.path, tasks, specsBaseDir);
-
- return { success: true, data: doneTasks };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CHANGELOG_LOAD_TASK_SPECS,
- async (_, projectId: string, taskIds: string[]): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const tasks = projectStore.getTasks(projectId);
-
- // Get specs directory path
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specs = await changelogService.loadTaskSpecs(project.path, taskIds, tasks, specsBaseDir);
-
- return { success: true, data: specs };
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.CHANGELOG_GENERATE,
- async (_, request: import('../shared/types').ChangelogGenerationRequest) => {
- const mainWindow = getMainWindow();
- if (!mainWindow) return;
-
- const project = projectStore.getProject(request.projectId);
- if (!project) {
- mainWindow.webContents.send(
- IPC_CHANNELS.CHANGELOG_GENERATION_ERROR,
- request.projectId,
- 'Project not found'
- );
- return;
- }
-
- // Load specs for selected tasks (only in tasks mode)
- let specs: import('../shared/types').TaskSpecContent[] = [];
- if (request.sourceMode === 'tasks' && request.taskIds && request.taskIds.length > 0) {
- const tasks = projectStore.getTasks(request.projectId);
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- specs = await changelogService.loadTaskSpecs(project.path, request.taskIds, tasks, specsBaseDir);
- }
-
- // Start generation
- changelogService.generateChangelog(request.projectId, project.path, request, specs);
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CHANGELOG_SAVE,
- async (_, request: import('../shared/types').ChangelogSaveRequest): Promise> => {
- const project = projectStore.getProject(request.projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- try {
- const result = changelogService.saveChangelog(project.path, request);
- return { success: true, data: result };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to save changelog'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CHANGELOG_READ_EXISTING,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const result = changelogService.readExistingChangelog(project.path);
- return { success: true, data: result };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CHANGELOG_SUGGEST_VERSION,
- async (_, projectId: string, taskIds: string[]): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- try {
- // Get current version from existing changelog
- const existing = changelogService.readExistingChangelog(project.path);
- const currentVersion = existing.lastVersion;
-
- // Load specs for selected tasks to analyze change types
- const tasks = projectStore.getTasks(projectId);
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specs = await changelogService.loadTaskSpecs(project.path, taskIds, tasks, specsBaseDir);
-
- // Analyze specs and suggest version
- const suggestedVersion = changelogService.suggestVersion(specs, currentVersion);
-
- // Determine reason for the suggestion
- let reason = 'patch';
- if (currentVersion) {
- const [oldMajor, oldMinor] = currentVersion.split('.').map(Number);
- const [newMajor, newMinor] = suggestedVersion.split('.').map(Number);
- if (newMajor > oldMajor) {
- reason = 'breaking';
- } else if (newMinor > oldMinor) {
- reason = 'feature';
- }
- }
-
- return {
- success: true,
- data: { version: suggestedVersion, reason }
- };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to suggest version'
- };
- }
- }
- );
-
- // ============================================
- // Changelog Git Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.CHANGELOG_GET_BRANCHES,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- try {
- const branches = changelogService.getBranches(project.path);
- return { success: true, data: branches };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get branches'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CHANGELOG_GET_TAGS,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- try {
- const tags = changelogService.getTags(project.path);
- return { success: true, data: tags };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get tags'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.CHANGELOG_GET_COMMITS_PREVIEW,
- async (
- _,
- projectId: string,
- options: import('../shared/types').GitHistoryOptions | import('../shared/types').BranchDiffOptions,
- mode: 'git-history' | 'branch-diff'
- ): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- try {
- let commits: import('../shared/types').GitCommit[];
-
- if (mode === 'git-history') {
- commits = changelogService.getCommits(
- project.path,
- options as import('../shared/types').GitHistoryOptions
- );
- } else {
- commits = changelogService.getBranchDiffCommits(
- project.path,
- options as import('../shared/types').BranchDiffOptions
- );
- }
-
- return { success: true, data: commits };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get commits preview'
- };
- }
- }
- );
-
- // ============================================
- // Changelog Agent Events → Renderer
- // ============================================
-
- changelogService.on('generation-progress', (projectId: string, progress: import('../shared/types').ChangelogGenerationProgress) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.CHANGELOG_GENERATION_PROGRESS, projectId, progress);
- }
- });
-
- changelogService.on('generation-complete', (projectId: string, result: import('../shared/types').ChangelogGenerationResult) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.CHANGELOG_GENERATION_COMPLETE, projectId, result);
- }
- });
-
- changelogService.on('generation-error', (projectId: string, error: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.CHANGELOG_GENERATION_ERROR, projectId, error);
- }
- });
-
- changelogService.on('rate-limit', (projectId: string, rateLimitInfo: import('../shared/types').SDKRateLimitInfo) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.CLAUDE_SDK_RATE_LIMIT, rateLimitInfo);
- }
- });
-
- // ============================================
- // Insights Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.INSIGHTS_GET_SESSION,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const session = insightsService.loadSession(projectId, project.path);
- return { success: true, data: session };
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.INSIGHTS_SEND_MESSAGE,
- async (_, projectId: string, message: string) => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.INSIGHTS_ERROR, projectId, 'Project not found');
- }
- return;
- }
-
- // Ensure Python environment is ready before sending message
- if (!pythonEnvManager.isEnvReady()) {
- const autoBuildSource = getAutoBuildSourcePath();
- if (autoBuildSource) {
- const status = await pythonEnvManager.initialize(autoBuildSource);
- if (status.ready && status.pythonPath) {
- configureServicesWithPython(status.pythonPath, autoBuildSource);
- } else {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(
- IPC_CHANNELS.INSIGHTS_ERROR,
- projectId,
- status.error || 'Python environment not ready'
- );
- }
- return;
- }
- }
- }
-
- insightsService.sendMessage(projectId, project.path, message);
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.INSIGHTS_CLEAR_SESSION,
- async (_, projectId: string): Promise => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- insightsService.clearSession(projectId, project.path);
- return { success: true };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.INSIGHTS_CREATE_TASK,
- async (
- _,
- projectId: string,
- title: string,
- description: string,
- metadata?: TaskMetadata
- ): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- if (!project.autoBuildPath) {
- return { success: false, error: 'Auto Claude not initialized for this project' };
- }
-
- try {
- // Generate a unique spec ID based on existing specs
- // Get specs directory path
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specsDir = path.join(project.path, specsBaseDir);
-
- // Find next available spec number
- let specNumber = 1;
- if (existsSync(specsDir)) {
- const existingDirs = readdirSync(specsDir, { withFileTypes: true })
- .filter(d => d.isDirectory())
- .map(d => d.name);
-
- const existingNumbers = existingDirs
- .map(name => {
- const match = name.match(/^(\d+)/);
- return match ? parseInt(match[1], 10) : 0;
- })
- .filter(n => n > 0);
-
- if (existingNumbers.length > 0) {
- specNumber = Math.max(...existingNumbers) + 1;
- }
- }
-
- // Create spec ID with zero-padded number and slugified title
- const slugifiedTitle = title
- .toLowerCase()
- .replace(/[^a-z0-9]+/g, '-')
- .replace(/^-|-$/g, '')
- .substring(0, 50);
- const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`;
-
- // Create spec directory
- const specDir = path.join(specsDir, specId);
- mkdirSync(specDir, { recursive: true });
-
- // Build metadata with source type
- const taskMetadata: TaskMetadata = {
- sourceType: 'insights',
- ...metadata
- };
-
- // Create initial implementation_plan.json
- const now = new Date().toISOString();
- const implementationPlan = {
- feature: title,
- description: description,
- created_at: now,
- updated_at: now,
- status: 'pending',
- phases: []
- };
-
- const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN);
- writeFileSync(planPath, JSON.stringify(implementationPlan, null, 2));
-
- // Save task metadata
- const metadataPath = path.join(specDir, 'task_metadata.json');
- writeFileSync(metadataPath, JSON.stringify(taskMetadata, null, 2));
-
- // Create the task object
- const task: Task = {
- id: specId,
- specId: specId,
- projectId,
- title,
- description,
- status: 'backlog',
- subtasks: [],
- logs: [],
- metadata: taskMetadata,
- createdAt: new Date(),
- updatedAt: new Date()
- };
-
- return { success: true, data: task };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to create task'
- };
- }
- }
- );
-
- // List all sessions for a project
- ipcMain.handle(
- IPC_CHANNELS.INSIGHTS_LIST_SESSIONS,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const sessions = insightsService.listSessions(project.path);
- return { success: true, data: sessions };
- }
- );
-
- // Create a new session
- ipcMain.handle(
- IPC_CHANNELS.INSIGHTS_NEW_SESSION,
- async (_, projectId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const session = insightsService.createNewSession(projectId, project.path);
- return { success: true, data: session };
- }
- );
-
- // Switch to a different session
- ipcMain.handle(
- IPC_CHANNELS.INSIGHTS_SWITCH_SESSION,
- async (_, projectId: string, sessionId: string): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const session = insightsService.switchSession(projectId, project.path, sessionId);
- return { success: true, data: session };
- }
- );
-
- // Delete a session
- ipcMain.handle(
- IPC_CHANNELS.INSIGHTS_DELETE_SESSION,
- async (_, projectId: string, sessionId: string): Promise => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const success = insightsService.deleteSession(projectId, project.path, sessionId);
- if (success) {
- return { success: true };
- }
- return { success: false, error: 'Failed to delete session' };
- }
- );
-
- // Rename a session
- ipcMain.handle(
- IPC_CHANNELS.INSIGHTS_RENAME_SESSION,
- async (_, projectId: string, sessionId: string, newTitle: string): Promise => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const success = insightsService.renameSession(project.path, sessionId, newTitle);
- if (success) {
- return { success: true };
- }
- return { success: false, error: 'Failed to rename session' };
- }
- );
-
- // ============================================
- // File Explorer Operations
- // ============================================
-
- // Directories to ignore when listing
- const IGNORED_DIRS = new Set([
- 'node_modules', '.git', '__pycache__', 'dist', 'build',
- '.next', '.nuxt', 'coverage', '.cache', '.venv', 'venv',
- '.idea', '.vscode', 'out', '.turbo', '.auto-claude',
- '.worktrees', 'vendor', 'target', '.gradle', '.maven'
- ]);
-
- ipcMain.handle(
- IPC_CHANNELS.FILE_EXPLORER_LIST,
- async (_, dirPath: string): Promise> => {
- try {
- const entries = readdirSync(dirPath, { withFileTypes: true });
-
- // Filter and map entries
- const nodes: FileNode[] = [];
- for (const entry of entries) {
- // Skip hidden files (except .env which is often useful)
- if (entry.name.startsWith('.') && entry.name !== '.env') continue;
- // Skip ignored directories
- if (entry.isDirectory() && IGNORED_DIRS.has(entry.name)) continue;
-
- nodes.push({
- path: path.join(dirPath, entry.name),
- name: entry.name,
- isDirectory: entry.isDirectory()
- });
- }
-
- // Sort: directories first, then alphabetically
- nodes.sort((a, b) => {
- if (a.isDirectory && !b.isDirectory) return -1;
- if (!a.isDirectory && b.isDirectory) return 1;
- return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });
- });
-
- return { success: true, data: nodes };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to read directory'
- };
- }
- }
- );
-
- // ============================================
- // Insights Agent Events → Renderer
- // ============================================
-
- insightsService.on('stream-chunk', (projectId: string, chunk: InsightsStreamChunk) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.INSIGHTS_STREAM_CHUNK, projectId, chunk);
- }
- });
-
- insightsService.on('status', (projectId: string, status: InsightsChatStatus) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.INSIGHTS_STATUS, projectId, status);
- }
- });
-
- insightsService.on('error', (projectId: string, error: string) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.INSIGHTS_ERROR, projectId, error);
- }
- });
-
- // Handle SDK rate limit events from insights service
- insightsService.on('sdk-rate-limit', (rateLimitInfo: import('../shared/types').SDKRateLimitInfo) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.CLAUDE_SDK_RATE_LIMIT, rateLimitInfo);
- }
- });
-}
diff --git a/auto-claude-ui/src/main/ipc-handlers/docker-handlers.ts b/auto-claude-ui/src/main/ipc-handlers/docker-handlers.ts
deleted file mode 100644
index 7d818a80..00000000
--- a/auto-claude-ui/src/main/ipc-handlers/docker-handlers.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Docker & Infrastructure IPC Handlers
- *
- * DEPRECATED: This file is kept for backward compatibility.
- * Memory infrastructure has moved to LadybugDB (no Docker required).
- * See memory-handlers.ts for the new implementation.
- *
- * This file now re-exports from memory-handlers.ts
- */
-
-import { registerMemoryHandlers } from './memory-handlers';
-
-/**
- * Register all Docker-related IPC handlers
- * @deprecated Use registerMemoryHandlers() instead
- */
-export function registerDockerHandlers(): void {
- // Register the new memory handlers instead
- registerMemoryHandlers();
-}
diff --git a/auto-claude-ui/src/main/ipc-handlers/task-handlers.ts.backup b/auto-claude-ui/src/main/ipc-handlers/task-handlers.ts.backup
deleted file mode 100644
index e4f1f7f4..00000000
--- a/auto-claude-ui/src/main/ipc-handlers/task-handlers.ts.backup
+++ /dev/null
@@ -1,1885 +0,0 @@
-import { ipcMain, BrowserWindow } from 'electron';
-import { IPC_CHANNELS, AUTO_BUILD_PATHS, getSpecsDir } from '../../shared/constants';
-import type { IPCResult, Task, TaskMetadata, TaskStartOptions, ImplementationPlan, TaskStatus, Project } from '../../shared/types';
-import path from 'path';
-import { existsSync, readFileSync, writeFileSync, readdirSync, mkdirSync, rmSync, statSync } from 'fs';
-import { execSync, spawn } from 'child_process';
-import { projectStore } from '../project-store';
-import { fileWatcher } from '../file-watcher';
-import { taskLogService } from '../task-log-service';
-import { titleGenerator } from '../title-generator';
-import { AgentManager } from '../agent';
-import { PythonEnvManager } from '../python-env-manager';
-import { getEffectiveSourcePath } from '../auto-claude-updater';
-import { getProfileEnv } from '../rate-limit-detector';
-
-
-/**
- * Register all task-related IPC handlers
- */
-export function registerTaskHandlers(
- agentManager: AgentManager,
- pythonEnvManager: PythonEnvManager,
- getMainWindow: () => BrowserWindow | null
-): void {
- // ============================================
- // Task Operations
- // ============================================
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_LIST,
- async (_, projectId: string): Promise> => {
- console.log('[IPC] TASK_LIST called with projectId:', projectId);
- const tasks = projectStore.getTasks(projectId);
- console.log('[IPC] TASK_LIST returning', tasks.length, 'tasks');
- return { success: true, data: tasks };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_CREATE,
- async (
- _,
- projectId: string,
- title: string,
- description: string,
- metadata?: TaskMetadata
- ): Promise> => {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- // Auto-generate title if empty using Claude AI
- let finalTitle = title;
- if (!title || !title.trim()) {
- console.log('[TASK_CREATE] Title is empty, generating with Claude AI...');
- try {
- const generatedTitle = await titleGenerator.generateTitle(description);
- if (generatedTitle) {
- finalTitle = generatedTitle;
- console.log('[TASK_CREATE] Generated title:', finalTitle);
- } else {
- // Fallback: create title from first line of description
- finalTitle = description.split('\n')[0].substring(0, 60);
- if (finalTitle.length === 60) finalTitle += '...';
- console.log('[TASK_CREATE] AI generation failed, using fallback:', finalTitle);
- }
- } catch (err) {
- console.error('[TASK_CREATE] Title generation error:', err);
- // Fallback: create title from first line of description
- finalTitle = description.split('\n')[0].substring(0, 60);
- if (finalTitle.length === 60) finalTitle += '...';
- }
- }
-
- // Generate a unique spec ID based on existing specs
- // Get specs directory path
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specsDir = path.join(project.path, specsBaseDir);
-
- // Find next available spec number
- let specNumber = 1;
- if (existsSync(specsDir)) {
- const existingDirs = readdirSync(specsDir, { withFileTypes: true })
- .filter(d => d.isDirectory())
- .map(d => d.name);
-
- // Extract numbers from spec directory names (e.g., "001-feature" -> 1)
- const existingNumbers = existingDirs
- .map(name => {
- const match = name.match(/^(\d+)/);
- return match ? parseInt(match[1], 10) : 0;
- })
- .filter(n => n > 0);
-
- if (existingNumbers.length > 0) {
- specNumber = Math.max(...existingNumbers) + 1;
- }
- }
-
- // Create spec ID with zero-padded number and slugified title
- const slugifiedTitle = finalTitle
- .toLowerCase()
- .replace(/[^a-z0-9]+/g, '-')
- .replace(/^-|-$/g, '')
- .substring(0, 50);
- const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`;
-
- // Create spec directory
- const specDir = path.join(specsDir, specId);
- mkdirSync(specDir, { recursive: true });
-
- // Build metadata with source type
- const taskMetadata: TaskMetadata = {
- sourceType: 'manual',
- ...metadata
- };
-
- // Process and save attached images
- if (taskMetadata.attachedImages && taskMetadata.attachedImages.length > 0) {
- const attachmentsDir = path.join(specDir, 'attachments');
- mkdirSync(attachmentsDir, { recursive: true });
-
- const savedImages: typeof taskMetadata.attachedImages = [];
-
- for (const image of taskMetadata.attachedImages) {
- if (image.data) {
- try {
- // Decode base64 and save to file
- const buffer = Buffer.from(image.data, 'base64');
- const imagePath = path.join(attachmentsDir, image.filename);
- writeFileSync(imagePath, buffer);
-
- // Store relative path instead of base64 data
- savedImages.push({
- id: image.id,
- filename: image.filename,
- mimeType: image.mimeType,
- size: image.size,
- path: `attachments/${image.filename}`
- // Don't include data or thumbnail to save space
- });
- } catch (err) {
- console.error(`Failed to save image ${image.filename}:`, err);
- }
- }
- }
-
- // Update metadata with saved image paths (without base64 data)
- taskMetadata.attachedImages = savedImages;
- }
-
- // Create initial implementation_plan.json (task is created but not started)
- const now = new Date().toISOString();
- const implementationPlan = {
- feature: finalTitle,
- description: description,
- created_at: now,
- updated_at: now,
- status: 'pending',
- phases: []
- };
-
- const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN);
- writeFileSync(planPath, JSON.stringify(implementationPlan, null, 2));
-
- // Save task metadata if provided
- if (taskMetadata) {
- const metadataPath = path.join(specDir, 'task_metadata.json');
- writeFileSync(metadataPath, JSON.stringify(taskMetadata, null, 2));
- }
-
- // Create requirements.json with attached images
- const requirements: Record = {
- task_description: description,
- workflow_type: taskMetadata.category || 'feature'
- };
-
- // Add attached images to requirements if present
- if (taskMetadata.attachedImages && taskMetadata.attachedImages.length > 0) {
- requirements.attached_images = taskMetadata.attachedImages.map(img => ({
- filename: img.filename,
- path: img.path,
- description: '' // User can add descriptions later
- }));
- }
-
- const requirementsPath = path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS);
- writeFileSync(requirementsPath, JSON.stringify(requirements, null, 2));
-
- // Create the task object
- const task: Task = {
- id: specId,
- specId: specId,
- projectId,
- title: finalTitle,
- description,
- status: 'backlog',
- subtasks: [],
- logs: [],
- metadata: taskMetadata,
- createdAt: new Date(),
- updatedAt: new Date()
- };
-
- return { success: true, data: task };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_DELETE,
- async (_, taskId: string): Promise => {
- const { rm } = await import('fs/promises');
-
- // Find task and project
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (!task || !project) {
- return { success: false, error: 'Task or project not found' };
- }
-
- // Check if task is currently running
- const isRunning = agentManager.isRunning(taskId);
- if (isRunning) {
- return { success: false, error: 'Cannot delete a running task. Stop the task first.' };
- }
-
- // Delete the spec directory
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(project.path, specsBaseDir, task.specId);
-
- try {
- if (existsSync(specDir)) {
- await rm(specDir, { recursive: true, force: true });
- console.log(`[TASK_DELETE] Deleted spec directory: ${specDir}`);
- }
- return { success: true };
- } catch (error) {
- console.error('[TASK_DELETE] Error deleting spec directory:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to delete task files'
- };
- }
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_UPDATE,
- async (
- _,
- taskId: string,
- updates: { title?: string; description?: string; metadata?: Partial }
- ): Promise> => {
- try {
- // Find task and project
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- const autoBuildDir = project.autoBuildPath || '.auto-claude';
- const specDir = path.join(project.path, autoBuildDir, 'specs', task.specId);
-
- if (!existsSync(specDir)) {
- return { success: false, error: 'Spec directory not found' };
- }
-
- // Auto-generate title if empty
- let finalTitle = updates.title;
- if (updates.title !== undefined && !updates.title.trim()) {
- // Get description to use for title generation
- const descriptionToUse = updates.description ?? task.description;
- console.log('[TASK_UPDATE] Title is empty, generating with Claude AI...');
- try {
- const generatedTitle = await titleGenerator.generateTitle(descriptionToUse);
- if (generatedTitle) {
- finalTitle = generatedTitle;
- console.log('[TASK_UPDATE] Generated title:', finalTitle);
- } else {
- // Fallback: create title from first line of description
- finalTitle = descriptionToUse.split('\n')[0].substring(0, 60);
- if (finalTitle.length === 60) finalTitle += '...';
- console.log('[TASK_UPDATE] AI generation failed, using fallback:', finalTitle);
- }
- } catch (err) {
- console.error('[TASK_UPDATE] Title generation error:', err);
- // Fallback: create title from first line of description
- finalTitle = descriptionToUse.split('\n')[0].substring(0, 60);
- if (finalTitle.length === 60) finalTitle += '...';
- }
- }
-
- // Update implementation_plan.json
- const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN);
- if (existsSync(planPath)) {
- try {
- const planContent = readFileSync(planPath, 'utf-8');
- const plan = JSON.parse(planContent);
-
- if (finalTitle !== undefined) {
- plan.feature = finalTitle;
- }
- if (updates.description !== undefined) {
- plan.description = updates.description;
- }
- plan.updated_at = new Date().toISOString();
-
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- } catch {
- // Plan file might not be valid JSON, continue anyway
- }
- }
-
- // Update spec.md if it exists
- const specPath = path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE);
- if (existsSync(specPath)) {
- try {
- let specContent = readFileSync(specPath, 'utf-8');
-
- // Update title (first # heading)
- if (finalTitle !== undefined) {
- specContent = specContent.replace(
- /^#\s+.*$/m,
- `# ${finalTitle}`
- );
- }
-
- // Update description (## Overview section content)
- if (updates.description !== undefined) {
- // Replace content between ## Overview and the next ## section
- specContent = specContent.replace(
- /(## Overview\n)([\s\S]*?)((?=\n## )|$)/,
- `$1${updates.description}\n\n$3`
- );
- }
-
- writeFileSync(specPath, specContent);
- } catch {
- // Spec file update failed, continue anyway
- }
- }
-
- // Update metadata if provided
- let updatedMetadata = task.metadata;
- if (updates.metadata) {
- updatedMetadata = { ...task.metadata, ...updates.metadata };
-
- // Process and save attached images if provided
- if (updates.metadata.attachedImages && updates.metadata.attachedImages.length > 0) {
- const attachmentsDir = path.join(specDir, 'attachments');
- mkdirSync(attachmentsDir, { recursive: true });
-
- const savedImages: typeof updates.metadata.attachedImages = [];
-
- for (const image of updates.metadata.attachedImages) {
- // If image has data (new image), save it
- if (image.data) {
- try {
- const buffer = Buffer.from(image.data, 'base64');
- const imagePath = path.join(attachmentsDir, image.filename);
- writeFileSync(imagePath, buffer);
-
- savedImages.push({
- id: image.id,
- filename: image.filename,
- mimeType: image.mimeType,
- size: image.size,
- path: `attachments/${image.filename}`
- });
- } catch (err) {
- console.error(`Failed to save image ${image.filename}:`, err);
- }
- } else if (image.path) {
- // Existing image, keep it
- savedImages.push(image);
- }
- }
-
- updatedMetadata.attachedImages = savedImages;
- }
-
- // Update task_metadata.json
- const metadataPath = path.join(specDir, 'task_metadata.json');
- try {
- writeFileSync(metadataPath, JSON.stringify(updatedMetadata, null, 2));
- } catch (err) {
- console.error('Failed to update task_metadata.json:', err);
- }
-
- // Update requirements.json if it exists
- const requirementsPath = path.join(specDir, 'requirements.json');
- if (existsSync(requirementsPath)) {
- try {
- const requirementsContent = readFileSync(requirementsPath, 'utf-8');
- const requirements = JSON.parse(requirementsContent);
-
- if (updates.description !== undefined) {
- requirements.task_description = updates.description;
- }
- if (updates.metadata.category) {
- requirements.workflow_type = updates.metadata.category;
- }
-
- writeFileSync(requirementsPath, JSON.stringify(requirements, null, 2));
- } catch (err) {
- console.error('Failed to update requirements.json:', err);
- }
- }
- }
-
- // Build the updated task object
- const updatedTask: Task = {
- ...task,
- title: finalTitle ?? task.title,
- description: updates.description ?? task.description,
- metadata: updatedMetadata,
- updatedAt: new Date()
- };
-
- return { success: true, data: updatedTask };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Unknown error'
- };
- }
- }
- );
-
- ipcMain.on(
- IPC_CHANNELS.TASK_START,
- (_, taskId: string, options?: TaskStartOptions) => {
- console.log('[TASK_START] Received request for taskId:', taskId);
- const mainWindow = getMainWindow();
- if (!mainWindow) {
- console.log('[TASK_START] No main window found');
- return;
- }
-
- // Find task and project
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (!task || !project) {
- console.log('[TASK_START] Task or project not found for taskId:', taskId);
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_ERROR,
- taskId,
- 'Task or project not found'
- );
- return;
- }
-
- console.log('[TASK_START] Found task:', task.specId, 'status:', task.status, 'subtasks:', task.subtasks.length);
-
- // Start file watcher for this task
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(
- project.path,
- specsBaseDir,
- task.specId
- );
- fileWatcher.watch(taskId, specDir);
-
- // Check if spec.md exists (indicates spec creation was already done or in progress)
- const specFilePath = path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE);
- const hasSpec = existsSync(specFilePath);
-
- // Check if this task needs spec creation first (no spec file = not yet created)
- // OR if it has a spec but no implementation plan subtasks (spec created, needs planning/building)
- const needsSpecCreation = !hasSpec;
- const needsImplementation = hasSpec && task.subtasks.length === 0;
-
- console.log('[TASK_START] hasSpec:', hasSpec, 'needsSpecCreation:', needsSpecCreation, 'needsImplementation:', needsImplementation);
-
- if (needsSpecCreation) {
- // No spec file - need to run spec_runner.py to create the spec
- const taskDescription = task.description || task.title;
- console.log('[TASK_START] Starting spec creation for:', task.specId, 'in:', specDir);
-
- // Start spec creation process - pass the existing spec directory
- // so spec_runner uses it instead of creating a new one
- agentManager.startSpecCreation(task.specId, project.path, taskDescription, specDir, task.metadata);
- } else if (needsImplementation) {
- // Spec exists but no subtasks - run run.py to create implementation plan and execute
- // Read the spec.md to get the task description
- let taskDescription = task.description || task.title;
- try {
- taskDescription = readFileSync(specFilePath, 'utf-8');
- } catch {
- // Use default description
- }
-
- console.log('[TASK_START] Starting task execution (no subtasks) for:', task.specId);
- // Start task execution which will create the implementation plan
- // Note: No parallel mode for planning phase - parallel only makes sense with multiple subtasks
- agentManager.startTaskExecution(
- taskId,
- project.path,
- task.specId,
- {
- parallel: false, // Sequential for planning phase
- workers: 1
- }
- );
- } else {
- // Task has subtasks, start normal execution
- // Note: Parallel execution is handled internally by the agent, not via CLI flags
- console.log('[TASK_START] Starting task execution (has subtasks) for:', task.specId);
-
- agentManager.startTaskExecution(
- taskId,
- project.path,
- task.specId,
- {
- parallel: false,
- workers: 1
- }
- );
- }
-
- // Notify status change
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- 'in_progress'
- );
- }
- );
-
- ipcMain.on(IPC_CHANNELS.TASK_STOP, (_, taskId: string) => {
- agentManager.killTask(taskId);
- fileWatcher.unwatch(taskId);
-
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- 'backlog'
- );
- }
- });
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_REVIEW,
- async (
- _,
- taskId: string,
- approved: boolean,
- feedback?: string
- ): Promise => {
- // Find task and project
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Check if dev mode is enabled for this project
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(
- project.path,
- specsBaseDir,
- task.specId
- );
-
- if (approved) {
- // Write approval to QA report
- const qaReportPath = path.join(specDir, AUTO_BUILD_PATHS.QA_REPORT);
- writeFileSync(
- qaReportPath,
- `# QA Review\n\nStatus: APPROVED\n\nReviewed at: ${new Date().toISOString()}\n`
- );
-
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- 'done'
- );
- }
- } else {
- // Write feedback for QA fixer
- const fixRequestPath = path.join(specDir, 'QA_FIX_REQUEST.md');
- writeFileSync(
- fixRequestPath,
- `# QA Fix Request\n\nStatus: REJECTED\n\n## Feedback\n\n${feedback || 'No feedback provided'}\n\nCreated at: ${new Date().toISOString()}\n`
- );
-
- // Restart QA process with dev mode
- agentManager.startQAProcess(taskId, project.path, task.specId);
-
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- 'in_progress'
- );
- }
- }
-
- return { success: true };
- }
- );
-
- ipcMain.handle(
- IPC_CHANNELS.TASK_UPDATE_STATUS,
- async (
- _,
- taskId: string,
- status: TaskStatus
- ): Promise => {
- // Find task and project
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Get the spec directory
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(
- project.path,
- specsBaseDir,
- task.specId
- );
-
- // Update implementation_plan.json if it exists
- const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN);
-
- try {
- if (existsSync(planPath)) {
- const planContent = readFileSync(planPath, 'utf-8');
- const plan = JSON.parse(planContent);
-
- // Store the exact UI status - project-store.ts will map it back
- plan.status = status;
- // Also store mapped version for Python compatibility
- plan.planStatus = status === 'done' ? 'completed'
- : status === 'in_progress' ? 'in_progress'
- : status === 'ai_review' ? 'review'
- : status === 'human_review' ? 'review'
- : 'pending';
- plan.updated_at = new Date().toISOString();
-
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- } else {
- // If no implementation plan exists yet, create a basic one
- const plan = {
- feature: task.title,
- description: task.description || '',
- created_at: task.createdAt.toISOString(),
- updated_at: new Date().toISOString(),
- status: status, // Store exact UI status for persistence
- planStatus: status === 'done' ? 'completed'
- : status === 'in_progress' ? 'in_progress'
- : status === 'ai_review' ? 'review'
- : status === 'human_review' ? 'review'
- : 'pending',
- phases: []
- };
-
- // Ensure spec directory exists
- if (!existsSync(specDir)) {
- mkdirSync(specDir, { recursive: true });
- }
-
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- }
-
- // Auto-start task when status changes to 'in_progress' and no process is running
- if (status === 'in_progress' && !agentManager.isRunning(taskId)) {
- const mainWindow = getMainWindow();
- console.log('[TASK_UPDATE_STATUS] Auto-starting task:', taskId);
-
- // Start file watcher for this task
- fileWatcher.watch(taskId, specDir);
-
- // Check if spec.md exists
- const specFilePath = path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE);
- const hasSpec = existsSync(specFilePath);
- const needsSpecCreation = !hasSpec;
- const needsImplementation = hasSpec && task.subtasks.length === 0;
-
- console.log('[TASK_UPDATE_STATUS] hasSpec:', hasSpec, 'needsSpecCreation:', needsSpecCreation, 'needsImplementation:', needsImplementation);
-
- if (needsSpecCreation) {
- // No spec file - need to run spec_runner.py to create the spec
- const taskDescription = task.description || task.title;
- console.log('[TASK_UPDATE_STATUS] Starting spec creation for:', task.specId);
- agentManager.startSpecCreation(task.specId, project.path, taskDescription, specDir, task.metadata);
- } else if (needsImplementation) {
- // Spec exists but no subtasks - run run.py to create implementation plan and execute
- console.log('[TASK_UPDATE_STATUS] Starting task execution (no subtasks) for:', task.specId);
- agentManager.startTaskExecution(
- taskId,
- project.path,
- task.specId,
- {
- parallel: false,
- workers: 1
- }
- );
- } else {
- // Task has subtasks, start normal execution
- // Note: Parallel execution is handled internally by the agent
- console.log('[TASK_UPDATE_STATUS] Starting task execution (has subtasks) for:', task.specId);
- agentManager.startTaskExecution(
- taskId,
- project.path,
- task.specId,
- {
- parallel: false,
- workers: 1
- }
- );
- }
-
- // Notify renderer about status change
- if (mainWindow) {
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- 'in_progress'
- );
- }
- }
-
- return { success: true };
- } catch (error) {
- console.error('Failed to update task status:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to update task status'
- };
- }
- }
- );
-
- // Handler to check if a task is actually running (has active process)
- ipcMain.handle(
- IPC_CHANNELS.TASK_CHECK_RUNNING,
- async (_, taskId: string): Promise> => {
- const isRunning = agentManager.isRunning(taskId);
- return { success: true, data: isRunning };
- }
- );
-
- // Handler to recover a stuck task (status says in_progress but no process running)
- ipcMain.handle(
- IPC_CHANNELS.TASK_RECOVER_STUCK,
- async (
- _,
- taskId: string,
- options?: { targetStatus?: TaskStatus; autoRestart?: boolean }
- ): Promise> => {
- const targetStatus = options?.targetStatus;
- const autoRestart = options?.autoRestart ?? false;
- // Check if task is actually running
- const isActuallyRunning = agentManager.isRunning(taskId);
-
- if (isActuallyRunning) {
- return {
- success: false,
- error: 'Task is still running. Stop it first before recovering.',
- data: {
- taskId,
- recovered: false,
- newStatus: 'in_progress' as TaskStatus,
- message: 'Task is still running'
- }
- };
- }
-
- // Find task and project
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Get the spec directory
- const autoBuildDir = project.autoBuildPath || '.auto-claude';
- const specDir = path.join(
- project.path,
- autoBuildDir,
- 'specs',
- task.specId
- );
-
- // Update implementation_plan.json
- const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN);
-
- try {
- // Read the plan to analyze subtask progress
- let plan: Record | null = null;
- if (existsSync(planPath)) {
- const planContent = readFileSync(planPath, 'utf-8');
- plan = JSON.parse(planContent);
- }
-
- // Determine the target status intelligently based on subtask progress
- // If targetStatus is explicitly provided, use it; otherwise calculate from subtasks
- let newStatus: TaskStatus = targetStatus || 'backlog';
-
- if (!targetStatus && plan?.phases && Array.isArray(plan.phases)) {
- // Analyze subtask statuses to determine appropriate recovery status
- const allSubtasks: Array<{ status: string }> = [];
- for (const phase of plan.phases as Array<{ subtasks?: Array<{ status: string }> }>) {
- if (phase.subtasks && Array.isArray(phase.subtasks)) {
- allSubtasks.push(...phase.subtasks);
- }
- }
-
- if (allSubtasks.length > 0) {
- const completedCount = allSubtasks.filter(s => s.status === 'completed').length;
- const allCompleted = completedCount === allSubtasks.length;
-
- if (allCompleted) {
- // All subtasks completed - should go to review (ai_review or human_review based on source)
- // For recovery, human_review is safer as it requires manual verification
- newStatus = 'human_review';
- } else if (completedCount > 0) {
- // Some subtasks completed, some still pending - task is in progress
- newStatus = 'in_progress';
- }
- // else: no subtasks completed, stay with 'backlog'
- }
- }
-
- if (plan) {
- // Update status
- plan.status = newStatus;
- plan.planStatus = newStatus === 'done' ? 'completed'
- : newStatus === 'in_progress' ? 'in_progress'
- : newStatus === 'ai_review' ? 'review'
- : newStatus === 'human_review' ? 'review'
- : 'pending';
- plan.updated_at = new Date().toISOString();
-
- // Add recovery note
- plan.recoveryNote = `Task recovered from stuck state at ${new Date().toISOString()}`;
-
- // Reset in_progress and failed subtask statuses to 'pending' so they can be retried
- // Keep completed subtasks as-is so run.py can resume from where it left off
- if (plan.phases && Array.isArray(plan.phases)) {
- for (const phase of plan.phases as Array<{ subtasks?: Array<{ status: string; actual_output?: string; started_at?: string; completed_at?: string }> }>) {
- if (phase.subtasks && Array.isArray(phase.subtasks)) {
- for (const subtask of phase.subtasks) {
- // Reset in_progress subtasks to pending (they were interrupted)
- // Keep completed subtasks as-is so run.py can resume
- if (subtask.status === 'in_progress') {
- subtask.status = 'pending';
- // Clear execution data to maintain consistency
- delete subtask.actual_output;
- delete subtask.started_at;
- delete subtask.completed_at;
- }
- // Also reset failed subtasks so they can be retried
- if (subtask.status === 'failed') {
- subtask.status = 'pending';
- // Clear execution data to maintain consistency
- delete subtask.actual_output;
- delete subtask.started_at;
- delete subtask.completed_at;
- }
- }
- }
- }
- }
-
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- }
-
- // Stop file watcher if it was watching this task
- fileWatcher.unwatch(taskId);
-
- // Auto-restart the task if requested
- let autoRestarted = false;
- if (autoRestart && project) {
- try {
- // Set status to in_progress for the restart
- newStatus = 'in_progress';
-
- // Update plan status for restart
- if (plan) {
- plan.status = 'in_progress';
- plan.planStatus = 'in_progress';
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- }
-
- // Start the task execution
- // Start file watcher for this task
- const specsBaseDir = getSpecsDir(project.autoBuildPath);
- const specDirForWatcher = path.join(project.path, specsBaseDir, task.specId);
- fileWatcher.watch(taskId, specDirForWatcher);
-
- // Note: Parallel execution is handled internally by the agent
- agentManager.startTaskExecution(
- taskId,
- project.path,
- task.specId,
- {
- parallel: false,
- workers: 1
- }
- );
-
- autoRestarted = true;
- console.log(`[Recovery] Auto-restarted task ${taskId}`);
- } catch (restartError) {
- console.error('Failed to auto-restart task after recovery:', restartError);
- // Recovery succeeded but restart failed - still report success
- }
- }
-
- // Notify renderer of status change
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(
- IPC_CHANNELS.TASK_STATUS_CHANGE,
- taskId,
- newStatus
- );
- }
-
- return {
- success: true,
- data: {
- taskId,
- recovered: true,
- newStatus,
- message: autoRestarted
- ? 'Task recovered and restarted successfully'
- : `Task recovered successfully and moved to ${newStatus}`,
- autoRestarted
- }
- };
- } catch (error) {
- console.error('Failed to recover stuck task:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to recover task'
- };
- }
- }
- );
-
- // ============================================
- // Workspace Management Operations (for human review)
- // ============================================
-
- /**
- * Helper function to find task and project by taskId
- */
- const findTaskAndProject = (taskId: string): { task: Task | undefined; project: Project | undefined } => {
- const projects = projectStore.getProjects();
- let task: Task | undefined;
- let project: Project | undefined;
-
- for (const p of projects) {
- const tasks = projectStore.getTasks(p.id);
- task = tasks.find((t) => t.id === taskId || t.specId === taskId);
- if (task) {
- project = p;
- break;
- }
- }
-
- return { task, project };
- };
-
- /**
- * Get the worktree status for a task
- * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_WORKTREE_STATUS,
- async (_, taskId: string): Promise> => {
- try {
- const { task, project } = findTaskAndProject(taskId);
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Per-spec worktree path: .worktrees/{spec-name}/
- const worktreePath = path.join(project.path, '.worktrees', task.specId);
-
- if (!existsSync(worktreePath)) {
- return {
- success: true,
- data: { exists: false }
- };
- }
-
- // Get branch info from git
- try {
- // Get current branch in worktree
- const branch = execSync('git rev-parse --abbrev-ref HEAD', {
- cwd: worktreePath,
- encoding: 'utf-8'
- }).trim();
-
- // Get base branch (usually main or master)
- let baseBranch = 'main';
- try {
- // Try to get the default branch
- baseBranch = execSync('git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo main', {
- cwd: project.path,
- encoding: 'utf-8'
- }).trim().replace('origin/', '');
- } catch {
- baseBranch = 'main';
- }
-
- // Get commit count
- let commitCount = 0;
- try {
- const countOutput = execSync(`git rev-list --count ${baseBranch}..HEAD 2>/dev/null || echo 0`, {
- cwd: worktreePath,
- encoding: 'utf-8'
- }).trim();
- commitCount = parseInt(countOutput, 10) || 0;
- } catch {
- commitCount = 0;
- }
-
- // Get diff stats
- let filesChanged = 0;
- let additions = 0;
- let deletions = 0;
-
- try {
- const diffStat = execSync(`git diff --stat ${baseBranch}...HEAD 2>/dev/null || echo ""`, {
- cwd: worktreePath,
- encoding: 'utf-8'
- }).trim();
-
- // Parse the summary line (e.g., "3 files changed, 50 insertions(+), 10 deletions(-)")
- const summaryMatch = diffStat.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/);
- if (summaryMatch) {
- filesChanged = parseInt(summaryMatch[1], 10) || 0;
- additions = parseInt(summaryMatch[2], 10) || 0;
- deletions = parseInt(summaryMatch[3], 10) || 0;
- }
- } catch {
- // Ignore diff errors
- }
-
- return {
- success: true,
- data: {
- exists: true,
- worktreePath,
- branch,
- baseBranch,
- commitCount,
- filesChanged,
- additions,
- deletions
- }
- };
- } catch (gitError) {
- console.error('Git error getting worktree status:', gitError);
- return {
- success: true,
- data: { exists: true, worktreePath }
- };
- }
- } catch (error) {
- console.error('Failed to get worktree status:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get worktree status'
- };
- }
- }
- );
-
- /**
- * Get the diff for a task's worktree
- * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_WORKTREE_DIFF,
- async (_, taskId: string): Promise> => {
- try {
- const { task, project } = findTaskAndProject(taskId);
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Per-spec worktree path: .worktrees/{spec-name}/
- const worktreePath = path.join(project.path, '.worktrees', task.specId);
-
- if (!existsSync(worktreePath)) {
- return { success: false, error: 'No worktree found for this task' };
- }
-
- // Get base branch
- let baseBranch = 'main';
- try {
- baseBranch = execSync('git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo main', {
- cwd: project.path,
- encoding: 'utf-8'
- }).trim().replace('origin/', '');
- } catch {
- baseBranch = 'main';
- }
-
- // Get the diff with file stats
- const files: import('../../shared/types').WorktreeDiffFile[] = [];
-
- try {
- // Get numstat for additions/deletions per file
- const numstat = execSync(`git diff --numstat ${baseBranch}...HEAD 2>/dev/null || echo ""`, {
- cwd: worktreePath,
- encoding: 'utf-8'
- }).trim();
-
- // Get name-status for file status
- const nameStatus = execSync(`git diff --name-status ${baseBranch}...HEAD 2>/dev/null || echo ""`, {
- cwd: worktreePath,
- encoding: 'utf-8'
- }).trim();
-
- // Parse name-status to get file statuses
- const statusMap: Record = {};
- nameStatus.split('\n').filter(Boolean).forEach((line: string) => {
- const [status, ...pathParts] = line.split('\t');
- const filePath = pathParts.join('\t'); // Handle files with tabs in name
- switch (status[0]) {
- case 'A': statusMap[filePath] = 'added'; break;
- case 'M': statusMap[filePath] = 'modified'; break;
- case 'D': statusMap[filePath] = 'deleted'; break;
- case 'R': statusMap[pathParts[1] || filePath] = 'renamed'; break;
- default: statusMap[filePath] = 'modified';
- }
- });
-
- // Parse numstat for additions/deletions
- numstat.split('\n').filter(Boolean).forEach((line: string) => {
- const [adds, dels, filePath] = line.split('\t');
- files.push({
- path: filePath,
- status: statusMap[filePath] || 'modified',
- additions: parseInt(adds, 10) || 0,
- deletions: parseInt(dels, 10) || 0
- });
- });
- } catch (diffError) {
- console.error('Error getting diff:', diffError);
- }
-
- // Generate summary
- const totalAdditions = files.reduce((sum, f) => sum + f.additions, 0);
- const totalDeletions = files.reduce((sum, f) => sum + f.deletions, 0);
- const summary = `${files.length} files changed, ${totalAdditions} insertions(+), ${totalDeletions} deletions(-)`;
-
- return {
- success: true,
- data: { files, summary }
- };
- } catch (error) {
- console.error('Failed to get worktree diff:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get worktree diff'
- };
- }
- }
- );
-
- /**
- * Merge the worktree changes into the main branch
- * @param taskId - The task ID to merge
- * @param options - Merge options { noCommit?: boolean }
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_WORKTREE_MERGE,
- async (_, taskId: string, options?: { noCommit?: boolean }): Promise> => {
- // Enable verbose debug logging via environment variables
- const DEBUG_MERGE = process.env.DEBUG_MERGE === 'true' || process.env.DEBUG === 'true';
- const debug = (...args: unknown[]) => {
- if (DEBUG_MERGE) console.log('[MERGE DEBUG]', ...args);
- };
-
- try {
- console.log('[MERGE] Handler called with taskId:', taskId, 'options:', options);
- debug('Starting merge for taskId:', taskId, 'options:', options);
-
- // Ensure Python environment is ready
- if (!pythonEnvManager.isEnvReady()) {
- const autoBuildSource = getEffectiveSourcePath();
- if (autoBuildSource) {
- const status = await pythonEnvManager.initialize(autoBuildSource);
- if (!status.ready) {
- return { success: false, error: `Python environment not ready: ${status.error || 'Unknown error'}` };
- }
- } else {
- return { success: false, error: 'Python environment not ready and Auto Claude source not found' };
- }
- }
-
- const { task, project } = findTaskAndProject(taskId);
- if (!task || !project) {
- debug('Task or project not found');
- return { success: false, error: 'Task not found' };
- }
-
- debug('Found task:', task.specId, 'project:', project.path);
-
- // Use run.py --merge to handle the merge
- const sourcePath = getEffectiveSourcePath();
- if (!sourcePath) {
- return { success: false, error: 'Auto Claude source not found' };
- }
-
- const runScript = path.join(sourcePath, 'run.py');
- const specDir = path.join(project.path, project.autoBuildPath || '.auto-claude', 'specs', task.specId);
-
- if (!existsSync(specDir)) {
- debug('Spec directory not found:', specDir);
- return { success: false, error: 'Spec directory not found' };
- }
-
- // Check worktree exists before merge
- const worktreePath = path.join(project.path, '.worktrees', task.specId);
- debug('Worktree path:', worktreePath, 'exists:', existsSync(worktreePath));
-
- // Get git status before merge
- if (DEBUG_MERGE) {
- try {
- const gitStatusBefore = execSync('git status --short', { cwd: project.path, encoding: 'utf-8' });
- debug('Git status BEFORE merge in main project:\n', gitStatusBefore || '(clean)');
- const gitBranch = execSync('git branch --show-current', { cwd: project.path, encoding: 'utf-8' }).trim();
- debug('Current branch:', gitBranch);
- } catch (e) {
- debug('Failed to get git status before:', e);
- }
- }
-
- const args = [
- runScript,
- '--spec', task.specId,
- '--project-dir', project.path,
- '--merge'
- ];
-
- // Add --no-commit flag if requested (stage changes without committing)
- if (options?.noCommit) {
- args.push('--no-commit');
- }
-
- const pythonPath = pythonEnvManager.getPythonPath() || 'python3';
- debug('Running command:', pythonPath, args.join(' '));
- debug('Working directory:', sourcePath);
-
- // Get profile environment with OAuth token for AI merge resolution
- const profileEnv = getProfileEnv();
- debug('Profile env for merge:', {
- hasOAuthToken: !!profileEnv.CLAUDE_CODE_OAUTH_TOKEN,
- hasConfigDir: !!profileEnv.CLAUDE_CONFIG_DIR
- });
-
- return new Promise((resolve) => {
- const mergeProcess = spawn(pythonPath, args, {
- cwd: sourcePath,
- env: {
- ...process.env,
- ...profileEnv, // Include active Claude profile OAuth token
- PYTHONUNBUFFERED: '1'
- }
- });
-
- let stdout = '';
- let stderr = '';
-
- mergeProcess.stdout.on('data', (data: Buffer) => {
- const chunk = data.toString();
- stdout += chunk;
- debug('STDOUT:', chunk);
- });
-
- mergeProcess.stderr.on('data', (data: Buffer) => {
- const chunk = data.toString();
- stderr += chunk;
- debug('STDERR:', chunk);
- });
-
- mergeProcess.on('close', (code: number) => {
- debug('Process exited with code:', code);
- debug('Full stdout:', stdout);
- debug('Full stderr:', stderr);
-
- // Get git status after merge
- if (DEBUG_MERGE) {
- try {
- const gitStatusAfter = execSync('git status --short', { cwd: project.path, encoding: 'utf-8' });
- debug('Git status AFTER merge in main project:\n', gitStatusAfter || '(clean)');
- const gitDiffStaged = execSync('git diff --staged --stat', { cwd: project.path, encoding: 'utf-8' });
- debug('Staged changes:\n', gitDiffStaged || '(none)');
- } catch (e) {
- debug('Failed to get git status after:', e);
- }
- }
-
- if (code === 0) {
- const isStageOnly = options?.noCommit === true;
-
- // For stage-only: keep in human_review so user commits manually
- // For full merge: mark as done
- const newStatus = isStageOnly ? 'human_review' : 'done';
- const planStatus = isStageOnly ? 'review' : 'completed';
-
- debug('Merge successful. isStageOnly:', isStageOnly, 'newStatus:', newStatus);
-
- // Persist the status change to implementation_plan.json
- const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN);
- try {
- if (existsSync(planPath)) {
- const planContent = readFileSync(planPath, 'utf-8');
- const plan = JSON.parse(planContent);
- plan.status = newStatus;
- plan.planStatus = planStatus;
- plan.updated_at = new Date().toISOString();
- if (isStageOnly) {
- plan.stagedAt = new Date().toISOString();
- plan.stagedInMainProject = true;
- }
- writeFileSync(planPath, JSON.stringify(plan, null, 2));
- }
- } catch (persistError) {
- console.error('Failed to persist task status:', persistError);
- }
-
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_STATUS_CHANGE, taskId, newStatus as TaskStatus);
- }
-
- const message = isStageOnly
- ? 'Changes staged in main project. Review with git status and commit when ready.'
- : 'Changes merged successfully';
-
- resolve({
- success: true,
- data: {
- success: true,
- message,
- staged: isStageOnly,
- projectPath: isStageOnly ? project.path : undefined
- }
- });
- } else {
- // Check if there were conflicts
- const hasConflicts = stdout.includes('conflict') || stderr.includes('conflict');
- debug('Merge failed. hasConflicts:', hasConflicts);
-
- resolve({
- success: true,
- data: {
- success: false,
- message: hasConflicts ? 'Merge conflicts detected' : `Merge failed: ${stderr || stdout}`,
- conflictFiles: hasConflicts ? [] : undefined
- }
- });
- }
- });
-
- mergeProcess.on('error', (err: Error) => {
- console.error('[MERGE] Process spawn error:', err);
- resolve({
- success: false,
- error: `Failed to run merge: ${err.message}`
- });
- });
- });
- } catch (error) {
- console.error('[MERGE] Exception in merge handler:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to merge worktree'
- };
- }
- }
- );
-
- /**
- * Discard the worktree changes
- * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_WORKTREE_DISCARD,
- async (_, taskId: string): Promise> => {
- try {
- const { task, project } = findTaskAndProject(taskId);
- if (!task || !project) {
- return { success: false, error: 'Task not found' };
- }
-
- // Per-spec worktree path: .worktrees/{spec-name}/
- const worktreePath = path.join(project.path, '.worktrees', task.specId);
-
- if (!existsSync(worktreePath)) {
- return {
- success: true,
- data: {
- success: true,
- message: 'No worktree to discard'
- }
- };
- }
-
- try {
- // Get the branch name before removing
- const branch = execSync('git rev-parse --abbrev-ref HEAD', {
- cwd: worktreePath,
- encoding: 'utf-8'
- }).trim();
-
- // Remove the worktree
- execSync(`git worktree remove --force "${worktreePath}"`, {
- cwd: project.path,
- encoding: 'utf-8'
- });
-
- // Delete the branch
- try {
- execSync(`git branch -D "${branch}"`, {
- cwd: project.path,
- encoding: 'utf-8'
- });
- } catch {
- // Branch might already be deleted or not exist
- }
-
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_STATUS_CHANGE, taskId, 'backlog');
- }
-
- return {
- success: true,
- data: {
- success: true,
- message: 'Worktree discarded successfully'
- }
- };
- } catch (gitError) {
- console.error('Git error discarding worktree:', gitError);
- return {
- success: false,
- error: `Failed to discard worktree: ${gitError instanceof Error ? gitError.message : 'Unknown error'}`
- };
- }
- } catch (error) {
- console.error('Failed to discard worktree:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to discard worktree'
- };
- }
- }
- );
-
- /**
- * List all spec worktrees for a project
- * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_LIST_WORKTREES,
- async (_, projectId: string): Promise> => {
- try {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const worktreesDir = path.join(project.path, '.worktrees');
- const worktrees: import('../../shared/types').WorktreeListItem[] = [];
-
- if (!existsSync(worktreesDir)) {
- return { success: true, data: { worktrees } };
- }
-
- // Get all directories in .worktrees
- const entries = readdirSync(worktreesDir);
- for (const entry of entries) {
- const entryPath = path.join(worktreesDir, entry);
- const stat = statSync(entryPath);
-
- // Skip worker directories and non-directories
- if (!stat.isDirectory() || entry.startsWith('worker-')) {
- continue;
- }
-
- try {
- // Get branch info
- const branch = execSync('git rev-parse --abbrev-ref HEAD', {
- cwd: entryPath,
- encoding: 'utf-8'
- }).trim();
-
- // Get base branch
- let baseBranch = 'main';
- try {
- baseBranch = execSync('git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo main', {
- cwd: project.path,
- encoding: 'utf-8'
- }).trim().replace('origin/', '');
- } catch {
- baseBranch = 'main';
- }
-
- // Get commit count
- let commitCount = 0;
- try {
- const countOutput = execSync(`git rev-list --count ${baseBranch}..HEAD 2>/dev/null || echo 0`, {
- cwd: entryPath,
- encoding: 'utf-8'
- }).trim();
- commitCount = parseInt(countOutput, 10) || 0;
- } catch {
- commitCount = 0;
- }
-
- // Get diff stats
- let filesChanged = 0;
- let additions = 0;
- let deletions = 0;
-
- try {
- const diffStat = execSync(`git diff --shortstat ${baseBranch}...HEAD 2>/dev/null || echo ""`, {
- cwd: entryPath,
- encoding: 'utf-8'
- }).trim();
-
- const filesMatch = diffStat.match(/(\d+) files? changed/);
- const addMatch = diffStat.match(/(\d+) insertions?/);
- const delMatch = diffStat.match(/(\d+) deletions?/);
-
- if (filesMatch) filesChanged = parseInt(filesMatch[1], 10) || 0;
- if (addMatch) additions = parseInt(addMatch[1], 10) || 0;
- if (delMatch) deletions = parseInt(delMatch[1], 10) || 0;
- } catch {
- // Ignore diff errors
- }
-
- worktrees.push({
- specName: entry,
- path: entryPath,
- branch,
- baseBranch,
- commitCount,
- filesChanged,
- additions,
- deletions
- });
- } catch (gitError) {
- console.error(`Error getting info for worktree ${entry}:`, gitError);
- // Skip this worktree if we can't get git info
- }
- }
-
- return { success: true, data: { worktrees } };
- } catch (error) {
- console.error('Failed to list worktrees:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to list worktrees'
- };
- }
- }
- );
-
- // ============================================
- // Task Logs Operations
- // ============================================
-
- /**
- * Get task logs from spec directory
- * Returns logs organized by phase (planning, coding, validation)
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_LOGS_GET,
- async (_, projectId: string, specId: string): Promise> => {
- try {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const specsRelPath = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(project.path, specsRelPath, specId);
-
- if (!existsSync(specDir)) {
- return { success: false, error: 'Spec directory not found' };
- }
-
- const logs = taskLogService.loadLogs(specDir, project.path, specsRelPath, specId);
- return { success: true, data: logs };
- } catch (error) {
- console.error('Failed to get task logs:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to get task logs'
- };
- }
- }
- );
-
- /**
- * Start watching a spec for log changes
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_LOGS_WATCH,
- async (_, projectId: string, specId: string): Promise => {
- try {
- const project = projectStore.getProject(projectId);
- if (!project) {
- return { success: false, error: 'Project not found' };
- }
-
- const specsRelPath = getSpecsDir(project.autoBuildPath);
- const specDir = path.join(project.path, specsRelPath, specId);
-
- if (!existsSync(specDir)) {
- return { success: false, error: 'Spec directory not found' };
- }
-
- taskLogService.startWatching(specId, specDir, project.path, specsRelPath);
- return { success: true };
- } catch (error) {
- console.error('Failed to start watching task logs:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to start watching'
- };
- }
- }
- );
-
- /**
- * Stop watching a spec for log changes
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_LOGS_UNWATCH,
- async (_, specId: string): Promise => {
- try {
- taskLogService.stopWatching(specId);
- return { success: true };
- } catch (error) {
- console.error('Failed to stop watching task logs:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to stop watching'
- };
- }
- }
- );
-
- /**
- * Preview merge conflicts before actually merging
- * Uses the smart merge system to analyze potential conflicts
- */
- ipcMain.handle(
- IPC_CHANNELS.TASK_WORKTREE_MERGE_PREVIEW,
- async (_, taskId: string): Promise> => {
- console.log('[IPC] TASK_WORKTREE_MERGE_PREVIEW called with taskId:', taskId);
- try {
- // Ensure Python environment is ready
- if (!pythonEnvManager.isEnvReady()) {
- console.log('[IPC] Python environment not ready, initializing...');
- const autoBuildSource = getEffectiveSourcePath();
- if (autoBuildSource) {
- const status = await pythonEnvManager.initialize(autoBuildSource);
- if (!status.ready) {
- console.error('[IPC] Python environment failed to initialize:', status.error);
- return { success: false, error: `Python environment not ready: ${status.error || 'Unknown error'}` };
- }
- } else {
- console.error('[IPC] Auto Claude source not found');
- return { success: false, error: 'Python environment not ready and Auto Claude source not found' };
- }
- }
-
- const { task, project } = findTaskAndProject(taskId);
- if (!task || !project) {
- console.error('[IPC] Task not found:', taskId);
- return { success: false, error: 'Task not found' };
- }
- console.log('[IPC] Found task:', task.specId, 'project:', project.name);
-
- const sourcePath = getEffectiveSourcePath();
- if (!sourcePath) {
- console.error('[IPC] Auto Claude source not found');
- return { success: false, error: 'Auto Claude source not found' };
- }
-
- const runScript = path.join(sourcePath, 'run.py');
- const args = [
- runScript,
- '--spec', task.specId,
- '--project-dir', project.path,
- '--merge-preview'
- ];
-
- const pythonPath = pythonEnvManager.getPythonPath() || 'python3';
- console.log('[IPC] Running merge preview:', pythonPath, args.join(' '));
-
- // Get profile environment for consistency
- const previewProfileEnv = getProfileEnv();
-
- return new Promise((resolve) => {
- const previewProcess = spawn(pythonPath, args, {
- cwd: sourcePath,
- env: { ...process.env, ...previewProfileEnv, PYTHONUNBUFFERED: '1', DEBUG: 'true' }
- });
-
- let stdout = '';
- let stderr = '';
-
- previewProcess.stdout.on('data', (data: Buffer) => {
- const chunk = data.toString();
- stdout += chunk;
- console.log('[IPC] merge-preview stdout:', chunk);
- });
-
- previewProcess.stderr.on('data', (data: Buffer) => {
- const chunk = data.toString();
- stderr += chunk;
- console.log('[IPC] merge-preview stderr:', chunk);
- });
-
- previewProcess.on('close', (code: number) => {
- console.log('[IPC] merge-preview process exited with code:', code);
- if (code === 0) {
- try {
- // Parse JSON output from Python
- const result = JSON.parse(stdout.trim());
- console.log('[IPC] merge-preview result:', JSON.stringify(result, null, 2));
- resolve({
- success: true,
- data: {
- success: result.success,
- message: result.error || 'Preview completed',
- preview: {
- files: result.files || [],
- conflicts: result.conflicts || [],
- summary: result.summary || {
- totalFiles: 0,
- conflictFiles: 0,
- totalConflicts: 0,
- autoMergeable: 0,
- hasGitConflicts: false
- },
- gitConflicts: result.gitConflicts || null
- }
- }
- });
- } catch (parseError) {
- console.error('[IPC] Failed to parse preview result:', parseError);
- console.error('[IPC] stdout:', stdout);
- console.error('[IPC] stderr:', stderr);
- resolve({
- success: false,
- error: `Failed to parse preview result: ${stderr || stdout}`
- });
- }
- } else {
- console.error('[IPC] Preview failed with exit code:', code);
- console.error('[IPC] stderr:', stderr);
- console.error('[IPC] stdout:', stdout);
- resolve({
- success: false,
- error: `Preview failed: ${stderr || stdout}`
- });
- }
- });
-
- previewProcess.on('error', (err: Error) => {
- console.error('[IPC] merge-preview spawn error:', err);
- resolve({
- success: false,
- error: `Failed to run preview: ${err.message}`
- });
- });
- });
- } catch (error) {
- console.error('[IPC] TASK_WORKTREE_MERGE_PREVIEW error:', error);
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to preview merge'
- };
- }
- }
- );
-
- // Setup task log service event forwarding to renderer
- taskLogService.on('logs-changed', (specId: string, logs: import('../../shared/types').TaskLogs) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_LOGS_CHANGED, specId, logs);
- }
- });
-
- taskLogService.on('stream-chunk', (specId: string, chunk: import('../../shared/types').TaskLogStreamChunk) => {
- const mainWindow = getMainWindow();
- if (mainWindow) {
- mainWindow.webContents.send(IPC_CHANNELS.TASK_LOGS_STREAM, specId, chunk);
- }
- });
-
-}
diff --git a/auto-claude-ui/src/renderer/components/project-settings/REFACTORING_SUMMARY.md b/auto-claude-ui/src/renderer/components/project-settings/REFACTORING_SUMMARY.md
deleted file mode 100644
index 451ca34e..00000000
--- a/auto-claude-ui/src/renderer/components/project-settings/REFACTORING_SUMMARY.md
+++ /dev/null
@@ -1,325 +0,0 @@
-# ProjectSettings Refactoring Summary
-
-## Overview
-
-Successfully refactored the monolithic `ProjectSettings.tsx` component (1,445 lines) into a modular, maintainable architecture with clear separation of concerns.
-
-## Metrics
-
-### Before Refactoring
-- **Total Lines**: 1,445 lines in a single file
-- **Components**: 1 monolithic component
-- **Hooks**: All logic embedded in component
-- **State Variables**: 15+ useState hooks in one component
-- **useEffect Hooks**: 7 complex effects managing different concerns
-
-### After Refactoring
-- **Main Component**: 321 lines (78% reduction)
-- **New Files Created**: 23 files
- - 7 section components
- - 5 utility components
- - 6 custom hooks
- - 2 index files
- - 2 documentation files
-- **Custom Hooks**: 6 specialized hooks for state management
-- **Reusable Components**: 5 utility components for common patterns
-
-## File Structure
-
-```
-ProjectSettings.tsx (321 lines) ← Main orchestrator
-├── Hooks (6 custom hooks)
-│ ├── useProjectSettings.ts
-│ ├── useEnvironmentConfig.ts
-│ ├── useClaudeAuth.ts
-│ ├── useLinearConnection.ts
-│ ├── useGitHubConnection.ts
-│ └── useInfrastructureStatus.ts
-│
-├── Section Components (7 feature components)
-│ ├── AutoBuildIntegration.tsx
-│ ├── ClaudeAuthSection.tsx
-│ ├── LinearIntegrationSection.tsx
-│ ├── GitHubIntegrationSection.tsx
-│ ├── MemoryBackendSection.tsx
-│ ├── AgentConfigSection.tsx
-│ └── NotificationsSection.tsx
-│
-└── Utility Components (5 reusable components)
- ├── CollapsibleSection.tsx
- ├── PasswordInput.tsx
- ├── StatusBadge.tsx
- ├── ConnectionStatus.tsx
- └── InfrastructureStatus.tsx
-```
-
-## Key Improvements
-
-### 1. Separation of Concerns
-
-**Before**: Single component handled everything
-- State management
-- API calls
-- UI rendering
-- Business logic
-- Effects management
-
-**After**: Clear responsibility boundaries
-- **Hooks**: State management and side effects
-- **Section Components**: Feature-specific UI and logic
-- **Utility Components**: Reusable UI patterns
-- **Main Component**: Orchestration and composition
-
-### 2. State Management
-
-**Before**: 15+ useState hooks in one place
-```tsx
-const [settings, setSettings] = useState(...)
-const [envConfig, setEnvConfig] = useState(...)
-const [isSaving, setIsSaving] = useState(...)
-const [error, setError] = useState(...)
-// ... 11 more state variables
-```
-
-**After**: Organized into custom hooks by domain
-```tsx
-// Clean, organized hook usage
-const { settings, setSettings, versionInfo } = useProjectSettings(project, open);
-const { envConfig, updateEnvConfig } = useEnvironmentConfig(project.id, ...);
-const { claudeAuthStatus } = useClaudeAuth(project.id, ...);
-```
-
-### 3. Component Composition
-
-**Before**: Deeply nested JSX with 800+ lines of markup
-```tsx
-return (
-
-);
-```
-
-**After**: Clean composition with semantic components
-```tsx
-return (
-
-);
-```
-
-### 4. Reusability
-
-**Before**: Repeated patterns throughout the file
-- Password inputs with show/hide (implemented 4 times)
-- Collapsible sections (implemented 4 times)
-- Status badges (inline everywhere)
-- Connection status displays (duplicated)
-
-**After**: DRY components used multiple times
-```tsx
-// Used in 4+ places
-
-
-// Used in 4 section components
-
- {children}
-
-
-// Used throughout for status display
-
-
-```
-
-### 5. Testing Capability
-
-**Before**: Nearly impossible to test
-- Single 1,445-line component
-- Tightly coupled logic
-- Mock entire component tree
-
-**After**: Fully testable in isolation
-```tsx
-// Test individual hooks
-describe('useClaudeAuth', () => {
- it('should check authentication status', () => { ... });
-});
-
-// Test individual components
-describe('ClaudeAuthSection', () => {
- it('should render authentication status', () => { ... });
-});
-
-// Test utility components
-describe('PasswordInput', () => {
- it('should toggle password visibility', () => { ... });
-});
-```
-
-## Component Breakdown by Size
-
-| Component | Lines | Purpose |
-|-----------|-------|---------|
-| ProjectSettings.tsx | 321 | Main orchestrator |
-| MemoryBackendSection.tsx | ~240 | Graphiti configuration (largest section) |
-| LinearIntegrationSection.tsx | ~160 | Linear integration |
-| GitHubIntegrationSection.tsx | ~140 | GitHub integration |
-| ClaudeAuthSection.tsx | ~100 | Claude authentication |
-| InfrastructureStatus.tsx | ~100 | Docker/FalkorDB status |
-| AutoBuildIntegration.tsx | ~70 | Auto-Build setup |
-| NotificationsSection.tsx | ~60 | Notification preferences |
-| AgentConfigSection.tsx | ~35 | Agent configuration |
-| CollapsibleSection.tsx | ~40 | Reusable wrapper |
-| ConnectionStatus.tsx | ~40 | Reusable status display |
-| PasswordInput.tsx | ~25 | Reusable input |
-| StatusBadge.tsx | ~15 | Reusable badge |
-
-## Hook Breakdown
-
-| Hook | Lines | Purpose |
-|------|-------|---------|
-| useInfrastructureStatus.ts | ~95 | Docker/FalkorDB monitoring |
-| useEnvironmentConfig.ts | ~75 | Environment config management |
-| useClaudeAuth.ts | ~55 | Claude auth checking |
-| useGitHubConnection.ts | ~45 | GitHub connection monitoring |
-| useLinearConnection.ts | ~40 | Linear connection monitoring |
-| useProjectSettings.ts | ~35 | Settings state management |
-
-## Type Safety Improvements
-
-**Before**: Implicit prop types, easy to break
-```tsx
-// No clear interface, props passed ad-hoc
-```
-
-**After**: Explicit interfaces for all components
-```tsx
-interface ClaudeAuthSectionProps {
- isExpanded: boolean;
- onToggle: () => void;
- envConfig: ProjectEnvConfig | null;
- isLoadingEnv: boolean;
- // ... all props explicitly typed
-}
-```
-
-## Maintainability Benefits
-
-### Easy to Locate Code
-- **Before**: Search through 1,445 lines to find Linear integration logic
-- **After**: Open `LinearIntegrationSection.tsx`
-
-### Easy to Modify
-- **Before**: Changing Linear logic risks breaking Claude, GitHub, or Graphiti
-- **After**: Change `LinearIntegrationSection.tsx` in isolation
-
-### Easy to Add Features
-- **Before**: Add 100+ lines to already massive component
-- **After**: Create new section component, add to main component
-
-### Easy to Debug
-- **Before**: Complex state interactions across entire component
-- **After**: Debug specific hook or component in isolation
-
-## Performance Considerations
-
-### Potential Optimizations Enabled
-1. **Memoization**: Can wrap individual sections with `React.memo()`
-2. **Code Splitting**: Can lazy load heavy sections
-3. **Selective Re-renders**: Changes to one section don't force re-render of others
-
-```tsx
-// Easy to add memoization
-export const MemoryBackendSection = React.memo(({ ... }) => {
- // Component logic
-});
-
-// Easy to lazy load
-const MemoryBackendSection = lazy(() => import('./MemoryBackendSection'));
-```
-
-## Migration Path
-
-### Zero Breaking Changes
-The refactored component maintains **100% compatibility** with existing usage:
-
-```tsx
-// Before refactoring
-
-
-// After refactoring (same API)
-
-```
-
-### Internal Structure Only
-- External API unchanged
-- Props interface unchanged
-- Behavior unchanged
-- Pure refactoring for code quality
-
-## Developer Experience
-
-### Before Refactoring
-- 😰 Overwhelming 1,445-line file
-- 🔍 Hard to find specific functionality
-- ⚠️ Risky to make changes
-- 🐛 Difficult to debug
-- 🚫 Can't work in parallel with other devs
-
-### After Refactoring
-- ✅ Small, focused files
-- 🎯 Easy to navigate by feature
-- 🛡️ Safe to modify isolated components
-- 🔬 Easy to debug specific sections
-- 👥 Multiple devs can work simultaneously
-
-## Code Quality Metrics
-
-### Complexity Reduction
-- **Cyclomatic Complexity**: Reduced from ~50+ to <10 per component
-- **Lines per File**: Average 60 lines (vs 1,445)
-- **Responsibilities**: 1 per component (vs 15+)
-
-### Maintainability Index
-- **Before**: Low (complex, large file)
-- **After**: High (simple, small files with clear purpose)
-
-## Next Steps
-
-### Immediate Benefits
-- ✅ Code is more maintainable
-- ✅ Components are reusable
-- ✅ Logic is testable
-- ✅ Team can work in parallel
-
-### Future Enhancements
-1. Add unit tests for each component and hook
-2. Add Storybook stories for visual testing
-3. Add performance monitoring
-4. Implement optimistic updates
-5. Add error boundaries
-6. Extract more common patterns
-
-## Conclusion
-
-This refactoring successfully transformed a monolithic, difficult-to-maintain component into a well-structured, modular architecture that follows React best practices and separation of concerns principles. The code is now:
-
-- **78% smaller** main component (321 vs 1,445 lines)
-- **Highly testable** with isolated units
-- **Easy to maintain** with clear responsibilities
-- **Reusable** with extracted utility components
-- **Type-safe** with explicit interfaces
-- **Developer-friendly** with clear organization
-
-All while maintaining 100% backward compatibility with zero breaking changes.
diff --git a/auto-claude/__init__.py b/auto-claude/__init__.py
deleted file mode 100644
index 57b862ea..00000000
--- a/auto-claude/__init__.py
+++ /dev/null
@@ -1,23 +0,0 @@
-"""
-Auto Claude - Autonomous Coding Framework
-==========================================
-
-Multi-agent autonomous coding framework that builds software through
-coordinated AI agent sessions.
-"""
-
-import json
-from pathlib import Path
-
-
-def _get_version() -> str:
- """Get version from package.json (single source of truth)."""
- package_json = Path(__file__).parent.parent / "auto-claude-ui" / "package.json"
- try:
- with open(package_json, encoding="utf-8") as f:
- return json.load(f).get("version", "0.0.0")
- except (FileNotFoundError, json.JSONDecodeError, KeyError):
- return "0.0.0"
-
-
-__version__ = _get_version()
diff --git a/auto-claude/agents/__init__.py b/auto-claude/agents/__init__.py
deleted file mode 100644
index 977fcb13..00000000
--- a/auto-claude/agents/__init__.py
+++ /dev/null
@@ -1,70 +0,0 @@
-"""
-Agents Module
-=============
-
-Modular agent system for autonomous coding.
-
-This module provides:
-- run_autonomous_agent: Main coder agent loop
-- run_followup_planner: Follow-up planner for completed specs
-- Memory management (Graphiti + file-based fallback)
-- Session management and post-processing
-- Utility functions for git and plan management
-"""
-
-# Main agent functions (public API)
-# Constants
-from .base import (
- AUTO_CONTINUE_DELAY_SECONDS,
- HUMAN_INTERVENTION_FILE,
-)
-from .coder import run_autonomous_agent
-
-# Memory functions
-from .memory_manager import (
- debug_memory_system_status,
- get_graphiti_context,
- save_session_memory,
- save_session_to_graphiti, # Backwards compatibility
-)
-from .planner import run_followup_planner
-
-# Session management
-from .session import (
- post_session_processing,
- run_agent_session,
-)
-
-# Utility functions
-from .utils import (
- find_phase_for_subtask,
- find_subtask_in_plan,
- get_commit_count,
- get_latest_commit,
- load_implementation_plan,
- sync_plan_to_source,
-)
-
-__all__ = [
- # Main API
- "run_autonomous_agent",
- "run_followup_planner",
- # Memory
- "debug_memory_system_status",
- "get_graphiti_context",
- "save_session_memory",
- "save_session_to_graphiti",
- # Session
- "run_agent_session",
- "post_session_processing",
- # Utils
- "get_latest_commit",
- "get_commit_count",
- "load_implementation_plan",
- "find_subtask_in_plan",
- "find_phase_for_subtask",
- "sync_plan_to_source",
- # Constants
- "AUTO_CONTINUE_DELAY_SECONDS",
- "HUMAN_INTERVENTION_FILE",
-]
diff --git a/auto-claude/analyzer.py b/auto-claude/analyzer.py
deleted file mode 100644
index 1cd4c705..00000000
--- a/auto-claude/analyzer.py
+++ /dev/null
@@ -1,7 +0,0 @@
-"""Backward compatibility shim - import from analysis.analyzer instead."""
-
-from analysis.analyzer import * # noqa: F403
-from analysis.analyzer import main
-
-if __name__ == "__main__":
- main()
diff --git a/auto-claude/analyzers/__init__.py b/auto-claude/analyzers/__init__.py
deleted file mode 100644
index e871cd82..00000000
--- a/auto-claude/analyzers/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""Backward compatibility shim - import from analysis.analyzers instead."""
-
-from analysis.analyzers import * # noqa: F403
diff --git a/auto-claude/auto_claude_tools.py b/auto-claude/auto_claude_tools.py
deleted file mode 100644
index 5c7cee4e..00000000
--- a/auto-claude/auto_claude_tools.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""Backward compatibility shim - import from agents.tools_pkg instead."""
-
-# Direct import to avoid triggering agents.__init__ circular dependencies
-import sys
-from pathlib import Path
-
-# Add agents directory to path if needed
-agents_dir = Path(__file__).parent / "agents"
-if str(agents_dir) not in sys.path:
- sys.path.insert(0, str(agents_dir))
-
-# Import directly from tools_pkg to avoid agents.__init__ circular imports
-from tools_pkg import * # noqa: F403, E402
diff --git a/auto-claude/client.py b/auto-claude/client.py
deleted file mode 100644
index 61271333..00000000
--- a/auto-claude/client.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""Backward compatibility shim - import from core.client instead."""
-
-import os
-import sys
-
-# Add auto-claude to path if not present
-_auto_claude_dir = os.path.dirname(os.path.abspath(__file__))
-if _auto_claude_dir not in sys.path:
- sys.path.insert(0, _auto_claude_dir)
-
-
-# Use lazy imports to avoid circular dependency
-def __getattr__(name):
- """Lazy import to avoid circular imports with auto_claude_tools."""
- from core import client as _client
-
- return getattr(_client, name)
diff --git a/auto-claude/debug.py b/auto-claude/debug.py
deleted file mode 100644
index e3759336..00000000
--- a/auto-claude/debug.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""Backward compatibility shim - import from core.debug instead."""
-
-from core.debug import * # noqa: F403
diff --git a/auto-claude/implementation_plan.py b/auto-claude/implementation_plan.py
deleted file mode 100644
index 6669efbe..00000000
--- a/auto-claude/implementation_plan.py
+++ /dev/null
@@ -1,4 +0,0 @@
-"""Backward compatibility shim - import from implementation_plan package instead."""
-
-from implementation_plan import * # noqa: F403
-from implementation_plan.main import * # noqa: F403
diff --git a/auto-claude/linear_integration.py b/auto-claude/linear_integration.py
deleted file mode 100644
index cf052f3a..00000000
--- a/auto-claude/linear_integration.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""Backward compatibility shim - import from integrations.linear.integration instead."""
-
-from integrations.linear.integration import * # noqa: F403
diff --git a/auto-claude/linear_updater.py b/auto-claude/linear_updater.py
deleted file mode 100644
index ab44130c..00000000
--- a/auto-claude/linear_updater.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""Backward compatibility shim - import from integrations.linear.updater instead."""
-
-from integrations.linear.updater import * # noqa: F403
diff --git a/auto-claude/merge/ARCHITECTURE.md b/auto-claude/merge/ARCHITECTURE.md
deleted file mode 100644
index 4e3ac5c7..00000000
--- a/auto-claude/merge/ARCHITECTURE.md
+++ /dev/null
@@ -1,200 +0,0 @@
-# File Timeline Architecture
-
-## Component Diagram
-
-```
-┌─────────────────────────────────────────────────────────────────┐
-│ file_timeline.py │
-│ (Public API Entry Point) │
-│ 83 lines │
-│ │
-│ Re-exports all public classes and functions │
-│ Maintains backward compatibility │
-└─────────────────────────────────────────────────────────────────┘
- │
- │ imports and re-exports
- ▼
-┌─────────────────────────────────────────────────────────────────┐
-│ timeline_tracker.py │
-│ (Main Coordination Service) │
-│ 560 lines │
-│ │
-│ ┌────────────────────────────────────────────────────────────┐ │
-│ │ FileTimelineTracker │ │
-│ │ • Event handlers (task start, commit, merge, abandon) │ │
-│ │ • Query methods (get context, files, drift, timeline) │ │
-│ │ • Worktree capture and initialization │ │
-│ └────────────────────────────────────────────────────────────┘ │
-└─────────────────────────────────────────────────────────────────┘
- │ │ │
- │ │ │
- ▼ ▼ ▼
-┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
-│ timeline_git.py │ │timeline_models.py│ │timeline_persist- │
-│ │ │ │ │ence.py │
-│ 256 lines │ │ 321 lines │ │ 136 lines │
-│ │ │ │ │ │
-│ ┌──────────────┐ │ │ Data Classes: │ │ ┌──────────────┐ │
-│ │TimelineGit- │ │ │ • MainBranchEvent│ │ │Timeline- │ │
-│ │Helper │ │ │ • BranchPoint │ │ │Persistence │ │
-│ │ │ │ │ • WorktreeState │ │ │ │ │
-│ │Git Ops: │ │ │ • TaskIntent │ │ │Storage: │ │
-│ │• File content│ │ │ • TaskFileView │ │ │• Load all │ │
-│ │• Commit info │ │ │ • FileTimeline │ │ │• Save one │ │
-│ │• Changed files│ │ │ • MergeContext │ │ │• Update index│ │
-│ │• Worktree ops│ │ │ │ │ │• File paths │ │
-│ └──────────────┘ │ │ Methods: │ │ └──────────────┘ │
-│ │ │ • to_dict() │ │ │
-│ │ │ • from_dict() │ │ │
-│ │ │ • Business logic │ │ │
-└──────────────────┘ └──────────────────┘ └──────────────────┘
-```
-
-## Data Flow
-
-### 1. Task Start Event
-```
-External Event (task starts)
- ↓
-FileTimelineTracker.on_task_start()
- ↓
-TimelineGitHelper.get_file_content_at_commit() ← Get branch point content
- ↓
-Create TaskFileView (timeline_models)
- ↓
-FileTimeline.add_task_view()
- ↓
-TimelinePersistence.save_timeline() ← Persist to disk
-```
-
-### 2. Main Branch Commit Event
-```
-Git Hook (post-commit)
- ↓
-FileTimelineTracker.on_main_branch_commit()
- ↓
-TimelineGitHelper.get_files_changed_in_commit()
- ↓
-TimelineGitHelper.get_file_content_at_commit()
- ↓
-TimelineGitHelper.get_commit_info()
- ↓
-Create MainBranchEvent (timeline_models)
- ↓
-FileTimeline.add_main_event() ← Updates drift counters
- ↓
-TimelinePersistence.save_timeline()
-```
-
-### 3. Get Merge Context
-```
-AI Resolver needs context
- ↓
-FileTimelineTracker.get_merge_context(task_id, file_path)
- ↓
-FileTimeline.get_task_view()
- ↓
-FileTimeline.get_events_since_commit() ← Main evolution
- ↓
-FileTimeline.get_current_main_state()
- ↓
-TimelineGitHelper.get_worktree_file_content()
- ↓
-FileTimeline.get_active_tasks() ← Other pending tasks
- ↓
-Build MergeContext (timeline_models)
- ↓
-Return to AI Resolver
-```
-
-## Separation of Concerns
-
-### timeline_models.py
-**Concern**: Data representation and serialization
-- Pure data classes with minimal logic
-- Serialization/deserialization methods
-- Basic query methods (no external dependencies)
-
-### timeline_git.py
-**Concern**: Git interaction
-- All git command execution
-- File content retrieval
-- Commit metadata queries
-- No business logic about timelines
-
-### timeline_persistence.py
-**Concern**: Storage and retrieval
-- JSON file operations
-- Index management
-- File path encoding
-- No knowledge of timeline business logic
-
-### timeline_tracker.py
-**Concern**: Business logic and coordination
-- Event handling workflow
-- Coordinate between git, models, and persistence
-- Build complex merge contexts
-- Manage timeline lifecycle
-
-### file_timeline.py
-**Concern**: Public API and backward compatibility
-- Re-export public interfaces
-- Documentation and usage examples
-- Entry point for external code
-
-## Benefits
-
-### Testability
-Each component can be tested in isolation:
-- **Models**: Test serialization, queries without git/filesystem
-- **Git**: Mock git commands, test parsing logic
-- **Persistence**: Mock filesystem, test save/load logic
-- **Tracker**: Mock all dependencies, test business logic
-
-### Reusability
-Components can be used independently:
-- `TimelineGitHelper` for any git operations
-- `TimelinePersistence` pattern for other storage needs
-- Models can be used without the full tracker
-
-### Maintainability
-Clear boundaries make changes easier:
-- Add git operation → Change only `timeline_git.py`
-- Add data field → Change only `timeline_models.py`
-- Change storage format → Change only `timeline_persistence.py`
-- Add event handler → Change only `timeline_tracker.py`
-
-### Type Safety
-All components have proper type hints:
-- Clear interfaces between components
-- IDE autocomplete support
-- Static type checking with mypy
-
-## Future Extensions
-
-The modular structure enables easy extensions:
-
-1. **Add SQLite backend**
- - Create `timeline_db_persistence.py`
- - Implement same interface as `TimelinePersistence`
- - Switch via configuration
-
-2. **Add caching layer**
- - Add `timeline_cache.py`
- - Cache git operations in `TimelineGitHelper`
- - LRU cache for frequently accessed timelines
-
-3. **Add timeline analytics**
- - Create `timeline_analytics.py`
- - Analyze drift patterns
- - Identify frequently conflicting files
-
-4. **Add visualization**
- - Create `timeline_visualizer.py`
- - Use the data models directly
- - Generate timeline graphs
-
-5. **Add async support**
- - Create `timeline_tracker_async.py`
- - Async git operations
- - Concurrent timeline updates
diff --git a/auto-claude/merge/REFACTORING_DETAILS.md b/auto-claude/merge/REFACTORING_DETAILS.md
deleted file mode 100644
index 4e04ceb7..00000000
--- a/auto-claude/merge/REFACTORING_DETAILS.md
+++ /dev/null
@@ -1,278 +0,0 @@
-# Detailed Refactoring Breakdown
-
-## What Moved Where
-
-This document provides a detailed mapping of where each component from the original `file_timeline.py` (992 lines) was relocated.
-
-### Original file_timeline.py Structure
-
-```
-Lines 1-59: Module docstring, imports, debug utilities
-Lines 61-115: MainBranchEvent class
-Lines 117-137: BranchPoint class
-Lines 139-157: WorktreeState class
-Lines 159-180: TaskIntent class
-Lines 182-230: TaskFileView class
-Lines 232-315: FileTimeline class
-Lines 317-365: MergeContext class
-Lines 367-992: FileTimelineTracker class + Git helpers
-```
-
-### New Module Breakdown
-
-#### timeline_models.py (321 lines)
-**Extracted from**: Lines 61-365 of original file
-
-Contains:
-- `MainBranchEvent` (lines 61-115) → Now lines 18-77
-- `BranchPoint` (lines 117-137) → Now lines 80-103
-- `WorktreeState` (lines 139-157) → Now lines 106-124
-- `TaskIntent` (lines 159-180) → Now lines 127-149
-- `TaskFileView` (lines 182-230) → Now lines 152-211
-- `FileTimeline` (lines 232-315) → Now lines 214-306
-- `MergeContext` (lines 317-365) → Now lines 309-321
-
-**Changes made**:
-- Added comprehensive module docstring
-- All imports moved to top
-- No functional changes to classes
-
-#### timeline_git.py (256 lines)
-**Extracted from**: Lines 785-875 + scattered helper methods
-
-Contains methods that were in FileTimelineTracker:
-- `_get_current_main_commit()` → Now `get_current_main_commit()`
-- `_get_file_content_at_commit()` → Now `get_file_content_at_commit()`
-- `_get_files_changed_in_commit()` → Now `get_files_changed_in_commit()`
-- `_get_commit_info()` → Now `get_commit_info()`
-- `_get_worktree_file_content()` → Now `get_worktree_file_content()`
-
-**Plus new helper methods**:
-- `get_changed_files_in_worktree()` - Extracted from `capture_worktree_state()`
-- `get_branch_point()` - Extracted from `initialize_from_worktree()`
-- `count_commits_between()` - Extracted from `initialize_from_worktree()`
-
-**Changes made**:
-- Wrapped in `TimelineGitHelper` class
-- Removed `_` prefix (now public methods)
-- Added comprehensive docstrings
-- Better error handling
-
-#### timeline_persistence.py (136 lines)
-**Extracted from**: Lines 717-779 of original file
-
-Contains methods that were in FileTimelineTracker:
-- `_load_from_storage()` → Now `load_all_timelines()`
-- `_persist_timeline()` → Now `save_timeline()`
-- `_update_index()` → Now `update_index()`
-- `_get_timeline_file_path()` → Now `_get_timeline_file_path()`
-
-**Changes made**:
-- Wrapped in `TimelinePersistence` class
-- Removed `_` prefix from public methods
-- Separated concerns (no timeline business logic)
-- Added comprehensive docstrings
-
-#### timeline_tracker.py (560 lines)
-**Extracted from**: Lines 372-992 of original file
-
-Contains the main `FileTimelineTracker` class with:
-
-**Event Handlers** (lines 414-608 of original):
-- `on_task_start()` - Simplified to use git helper
-- `on_main_branch_commit()` - Simplified to use git helper
-- `on_task_worktree_change()` - Unchanged
-- `on_task_merged()` - Simplified to use git helper
-- `on_task_abandoned()` - Unchanged
-
-**Query Methods** (lines 610-711 of original):
-- `get_merge_context()` - Simplified to use git helper
-- `get_files_for_task()` - Unchanged
-- `get_pending_tasks_for_file()` - Unchanged
-- `get_task_drift()` - Unchanged
-- `has_timeline()` - Unchanged
-- `get_timeline()` - Unchanged
-
-**Capture Methods** (lines 878-992 of original):
-- `capture_worktree_state()` - Simplified to use git helper
-- `initialize_from_worktree()` - Simplified to use git helper
-
-**Changes made**:
-- Now uses `TimelineGitHelper` for all git operations
-- Now uses `TimelinePersistence` for all storage operations
-- Removed all git subprocess calls (delegated to helper)
-- Removed all file I/O (delegated to persistence)
-- Focused on business logic and coordination
-
-#### file_timeline.py (83 lines)
-**New entry point** - Replaces original 992 line file
-
-Contains:
-- Comprehensive module docstring with usage examples
-- Architecture description
-- Re-exports of all public APIs
-- `__all__` declaration
-
-**Changes made**:
-- Complete rewrite as entry point
-- No business logic (pure re-exports)
-- Enhanced documentation
-- Backward compatibility maintained
-
-## Dependency Changes
-
-### Before Refactoring
-```
-file_timeline.py (992 lines)
-├── subprocess (git operations)
-├── json (persistence)
-├── pathlib (file operations)
-└── datetime, logging, dataclasses, typing
-```
-
-### After Refactoring
-```
-file_timeline.py (83 lines) - Entry point
-└── Re-exports from:
- ├── timeline_models.py (321 lines)
- │ └── datetime, dataclasses, typing
- │
- ├── timeline_git.py (256 lines)
- │ └── subprocess, pathlib, logging
- │
- ├── timeline_persistence.py (136 lines)
- │ └── json, pathlib, datetime, logging
- │
- └── timeline_tracker.py (560 lines)
- ├── timeline_models
- ├── timeline_git
- └── timeline_persistence
-```
-
-## Line Count Comparison
-
-| Original Section | Lines | New Module | Lines | Change |
-|-----------------|-------|------------|-------|--------|
-| Imports & Debug | 59 | Distributed | ~40 | Simplified |
-| Data Models | 305 | timeline_models.py | 321 | +16 (docs) |
-| FileTimelineTracker | 628 | timeline_tracker.py | 560 | -68 (delegation) |
-| Git Helpers | - | timeline_git.py | 256 | +256 (extracted) |
-| Persistence | - | timeline_persistence.py | 136 | +136 (extracted) |
-| Entry Point | - | file_timeline.py | 83 | +83 (new) |
-| **Total** | **992** | **All modules** | **1,356** | **+364** |
-
-The total line count increased by 364 lines (37%) due to:
-- More comprehensive documentation in each module
-- Clear module boundaries and interfaces
-- Explicit type hints throughout
-- Better error handling
-- Separation of concerns (less code reuse)
-
-However, the main entry point decreased by 91%, and each individual module is now much more maintainable.
-
-## Import Impact
-
-### Files That Import from file_timeline.py
-
-#### merge/__init__.py
-```python
-# Before (still works)
-from .file_timeline import (
- FileTimelineTracker,
- FileTimeline,
- MainBranchEvent,
- # ...
-)
-
-# After (same imports, different source)
-from .file_timeline import ( # Now re-exported from modular structure
- FileTimelineTracker,
- FileTimeline,
- MainBranchEvent,
- # ...
-)
-```
-**Status**: ✅ No changes needed - backward compatible
-
-#### merge/tracker_cli.py
-```python
-# Before and After (unchanged)
-from .file_timeline import FileTimelineTracker
-```
-**Status**: ✅ No changes needed - backward compatible
-
-#### merge/prompts.py
-```python
-# Before and After (unchanged)
-if TYPE_CHECKING:
- from .file_timeline import MergeContext, MainBranchEvent
-```
-**Status**: ✅ No changes needed - backward compatible
-
-### Advanced Usage (Optional)
-
-Users can now import from specific modules if needed:
-
-```python
-# Import from specific modules (new capability)
-from merge.timeline_models import FileTimeline, MergeContext
-from merge.timeline_git import TimelineGitHelper
-from merge.timeline_persistence import TimelinePersistence
-from merge.timeline_tracker import FileTimelineTracker
-
-# Or continue using the entry point (backward compatible)
-from merge.file_timeline import FileTimelineTracker, MergeContext
-```
-
-## Testing Coverage
-
-All original functionality is preserved:
-
-### Event Handlers
-- ✅ `on_task_start()` - Creates timeline for new task
-- ✅ `on_main_branch_commit()` - Updates main branch history
-- ✅ `on_task_worktree_change()` - Updates worktree state
-- ✅ `on_task_merged()` - Marks task as merged
-- ✅ `on_task_abandoned()` - Marks task as abandoned
-
-### Query Methods
-- ✅ `get_merge_context()` - Builds complete merge context
-- ✅ `get_files_for_task()` - Returns files for a task
-- ✅ `get_pending_tasks_for_file()` - Returns pending tasks
-- ✅ `get_task_drift()` - Returns commits behind main
-- ✅ `has_timeline()` - Checks if timeline exists
-- ✅ `get_timeline()` - Gets timeline for file
-
-### Capture Methods
-- ✅ `capture_worktree_state()` - Captures worktree state
-- ✅ `initialize_from_worktree()` - Initializes from existing worktree
-
-### Data Models
-- ✅ All 7 data models with serialization methods
-- ✅ All business logic methods on models
-- ✅ All type hints preserved
-
-## Future Maintenance
-
-With this refactoring, future changes become easier:
-
-### To add a new git operation:
-1. Add method to `TimelineGitHelper` in `timeline_git.py`
-2. Use it in `FileTimelineTracker` in `timeline_tracker.py`
-3. No changes to models or persistence
-
-### To change storage format:
-1. Modify `TimelinePersistence` in `timeline_persistence.py`
-2. No changes to tracker, models, or git operations
-
-### To add a new data field:
-1. Add field to model in `timeline_models.py`
-2. Update `to_dict()` and `from_dict()` methods
-3. Use new field in `FileTimelineTracker` if needed
-
-### To add a new event handler:
-1. Add method to `FileTimelineTracker` in `timeline_tracker.py`
-2. Use existing git helper and persistence methods
-3. No changes to other modules
-
-This separation of concerns makes the codebase much more maintainable going forward.
diff --git a/auto-claude/merge/REFACTORING_SUMMARY.md b/auto-claude/merge/REFACTORING_SUMMARY.md
deleted file mode 100644
index 8a3ca70c..00000000
--- a/auto-claude/merge/REFACTORING_SUMMARY.md
+++ /dev/null
@@ -1,182 +0,0 @@
-# File Timeline Refactoring Summary
-
-## Overview
-
-The `file_timeline.py` module (originally 992 lines) has been refactored into smaller, focused modules with clear separation of concerns. The main entry point is now only 83 lines, a **91% reduction**, while maintaining full backward compatibility.
-
-## New Module Structure
-
-### 1. `timeline_models.py` (321 lines)
-**Purpose**: Data classes for timeline representation
-
-**Contents**:
-- `MainBranchEvent` - Represents commits to main branch
-- `BranchPoint` - The exact point a task branched from main
-- `WorktreeState` - Current state of a file in a task's worktree
-- `TaskIntent` - What the task intends to do with a file
-- `TaskFileView` - A single task's relationship with a specific file
-- `FileTimeline` - Core data structure tracking a file's complete history
-- `MergeContext` - Complete context package for the Merge AI
-
-**Responsibilities**:
-- Define all data structures
-- Provide serialization/deserialization methods (`to_dict`/`from_dict`)
-- Implement basic timeline operations (add events, query tasks, etc.)
-
-### 2. `timeline_git.py` (256 lines)
-**Purpose**: Git operations and queries
-
-**Contents**:
-- `TimelineGitHelper` - Git operations helper class
-
-**Responsibilities**:
-- Get file content at specific commits
-- Query commit information and metadata
-- Determine changed files in commits
-- Work with worktrees
-- Count commits between points
-
-### 3. `timeline_persistence.py` (136 lines)
-**Purpose**: Storage and loading of timelines
-
-**Contents**:
-- `TimelinePersistence` - Handles persistence of file timelines to disk
-
-**Responsibilities**:
-- Load all timelines from disk on startup
-- Save individual timelines to disk
-- Manage the timeline index file
-- Encode file paths for safe storage
-
-### 4. `timeline_tracker.py` (560 lines)
-**Purpose**: Main service coordinating all components
-
-**Contents**:
-- `FileTimelineTracker` - Central service managing all file timelines
-
-**Responsibilities**:
-- Handle events from git hooks and task lifecycle
-- Coordinate between git, persistence, and models
-- Provide merge context to the AI resolver
-- Implement event handlers (task start, commit, merge, etc.)
-- Implement query methods (get context, files, drift, etc.)
-- Capture worktree state
-
-### 5. `file_timeline.py` (83 lines)
-**Purpose**: Main entry point and public API
-
-**Contents**:
-- Documentation and usage examples
-- Re-exports of all public classes and functions
-
-**Responsibilities**:
-- Serve as the main entry point
-- Maintain backward compatibility
-- Provide clear documentation
-
-## Benefits of Refactoring
-
-### 1. Improved Maintainability
-- **Smaller files**: Each module is focused on a single responsibility
-- **Easier to navigate**: Developers can quickly find relevant code
-- **Reduced cognitive load**: Each file has a clear, focused purpose
-
-### 2. Better Testability
-- **Isolated components**: Each module can be tested independently
-- **Mock-friendly**: Dependencies are clear and can be easily mocked
-- **Focused tests**: Tests can target specific functionality
-
-### 3. Clear Separation of Concerns
-- **Data models**: Pure data structures with no business logic
-- **Git operations**: Isolated from business logic
-- **Persistence**: Storage logic separated from data structures
-- **Coordination**: Main service coordinates components
-
-### 4. Type Safety
-- All modules use proper type hints
-- Clear interfaces between components
-- Better IDE support and autocomplete
-
-### 5. Reusability
-- Individual components can be used independently
-- Git helper can be reused for other git operations
-- Persistence layer follows a clear pattern for other modules
-
-## Backward Compatibility
-
-✅ **Full backward compatibility maintained**
-
-All existing imports continue to work:
-
-```python
-# These imports still work exactly as before
-from merge.file_timeline import FileTimelineTracker
-from merge.file_timeline import MergeContext
-from merge import FileTimelineTracker, MergeContext
-
-# Advanced usage now possible
-from merge.file_timeline import TimelineGitHelper
-from merge.file_timeline import TimelinePersistence
-```
-
-## Testing
-
-All import tests passed:
-- ✅ Direct module imports work
-- ✅ Package-level imports work (`from merge import ...`)
-- ✅ Dependent modules (tracker_cli, prompts, __init__) work correctly
-- ✅ No syntax errors in any new module
-
-## File Size Comparison
-
-| File | Lines | Percentage |
-|------|-------|------------|
-| **Original** `file_timeline.py` | 992 | 100% |
-| **New** `file_timeline.py` (entry point) | 83 | 8% |
-| `timeline_models.py` | 321 | 32% |
-| `timeline_git.py` | 256 | 26% |
-| `timeline_persistence.py` | 136 | 14% |
-| `timeline_tracker.py` | 560 | 56% |
-| **Total** (all new files) | 1,356 | 137% |
-
-Note: The total is slightly larger due to:
-- Additional documentation in each module
-- Clear module boundaries and interfaces
-- More explicit type hints
-- Better error handling
-
-## Migration Guide
-
-No migration needed! All existing code continues to work without changes.
-
-### Optional: Use New Modular Structure
-
-If you want to use the new modular structure for advanced use cases:
-
-```python
-# Old way (still works)
-from merge.file_timeline import FileTimelineTracker
-
-# New way (also works, more explicit)
-from merge.timeline_tracker import FileTimelineTracker
-from merge.timeline_models import MergeContext
-from merge.timeline_git import TimelineGitHelper
-
-# Use individual components
-git_helper = TimelineGitHelper(project_path)
-content = git_helper.get_file_content_at_commit("src/App.tsx", "abc123")
-```
-
-## Future Improvements
-
-Now that the code is modular, future improvements are easier:
-
-1. **Add caching** to `TimelineGitHelper` for better performance
-2. **Add database backend** option to `TimelinePersistence`
-3. **Add timeline analytics** to `FileTimeline` model
-4. **Add timeline visualization** using the separated data models
-5. **Add comprehensive unit tests** for each module independently
-
-## Conclusion
-
-This refactoring successfully improves code quality and maintainability while maintaining full backward compatibility. The modular structure makes the code easier to understand, test, and extend.
diff --git a/auto-claude/merge/auto_merger_old.py b/auto-claude/merge/auto_merger_old.py
deleted file mode 100644
index 64cd7e2b..00000000
--- a/auto-claude/merge/auto_merger_old.py
+++ /dev/null
@@ -1,654 +0,0 @@
-"""
-Auto Merger
-===========
-
-Deterministic merge strategies that don't require AI intervention.
-
-This module implements the merge strategies identified by ConflictDetector
-as auto-mergeable. Each strategy is a pure Python algorithm that combines
-changes from multiple tasks in a predictable way.
-
-Strategies:
-- COMBINE_IMPORTS: Merge import statements from multiple tasks
-- HOOKS_FIRST: Add hooks at function start, then other changes
-- HOOKS_THEN_WRAP: Add hooks first, then wrap return in JSX
-- APPEND_FUNCTIONS: Add new functions after existing ones
-- APPEND_METHODS: Add new methods to class
-- COMBINE_PROPS: Merge JSX/object props
-- ORDER_BY_DEPENDENCY: Analyze dependencies and order appropriately
-- ORDER_BY_TIME: Apply changes in chronological order
-"""
-
-from __future__ import annotations
-
-import logging
-import re
-from dataclasses import dataclass
-from pathlib import Path
-
-from .types import (
- ChangeType,
- ConflictRegion,
- MergeDecision,
- MergeResult,
- MergeStrategy,
- SemanticChange,
- TaskSnapshot,
-)
-
-logger = logging.getLogger(__name__)
-
-
-@dataclass
-class MergeContext:
- """Context for a merge operation."""
-
- file_path: str
- baseline_content: str
- task_snapshots: list[TaskSnapshot]
- conflict: ConflictRegion
-
-
-class AutoMerger:
- """
- Performs deterministic merges without AI.
-
- This class implements various merge strategies that can be applied
- when the ConflictDetector determines changes are compatible.
-
- Example:
- merger = AutoMerger()
- result = merger.merge(context, MergeStrategy.COMBINE_IMPORTS)
- if result.success:
- print(result.merged_content)
- """
-
- def __init__(self):
- """Initialize the auto merger."""
- self._strategy_handlers = {
- MergeStrategy.COMBINE_IMPORTS: self._merge_combine_imports,
- MergeStrategy.HOOKS_FIRST: self._merge_hooks_first,
- MergeStrategy.HOOKS_THEN_WRAP: self._merge_hooks_then_wrap,
- MergeStrategy.APPEND_FUNCTIONS: self._merge_append_functions,
- MergeStrategy.APPEND_METHODS: self._merge_append_methods,
- MergeStrategy.COMBINE_PROPS: self._merge_combine_props,
- MergeStrategy.ORDER_BY_DEPENDENCY: self._merge_order_by_dependency,
- MergeStrategy.ORDER_BY_TIME: self._merge_order_by_time,
- MergeStrategy.APPEND_STATEMENTS: self._merge_append_statements,
- }
-
- def merge(
- self,
- context: MergeContext,
- strategy: MergeStrategy,
- ) -> MergeResult:
- """
- Perform a merge using the specified strategy.
-
- Args:
- context: The merge context with baseline and task snapshots
- strategy: The merge strategy to use
-
- Returns:
- MergeResult with merged content or error
- """
- handler = self._strategy_handlers.get(strategy)
-
- if not handler:
- return MergeResult(
- decision=MergeDecision.FAILED,
- file_path=context.file_path,
- error=f"No handler for strategy: {strategy.value}",
- )
-
- try:
- return handler(context)
- except Exception as e:
- logger.exception(f"Auto-merge failed with strategy {strategy.value}")
- return MergeResult(
- decision=MergeDecision.FAILED,
- file_path=context.file_path,
- error=f"Auto-merge failed: {str(e)}",
- )
-
- def can_handle(self, strategy: MergeStrategy) -> bool:
- """Check if this merger can handle a strategy."""
- return strategy in self._strategy_handlers
-
- # ========================================
- # Strategy Implementations
- # ========================================
-
- def _merge_combine_imports(self, context: MergeContext) -> MergeResult:
- """Combine import statements from multiple tasks."""
- lines = context.baseline_content.split("\n")
- ext = Path(context.file_path).suffix.lower()
-
- # Collect all imports to add
- imports_to_add: list[str] = []
- imports_to_remove: set[str] = set()
-
- for snapshot in context.task_snapshots:
- for change in snapshot.semantic_changes:
- if change.change_type == ChangeType.ADD_IMPORT and change.content_after:
- imports_to_add.append(change.content_after.strip())
- elif (
- change.change_type == ChangeType.REMOVE_IMPORT
- and change.content_before
- ):
- imports_to_remove.add(change.content_before.strip())
-
- # Find where imports end in the file
- import_end_line = self._find_import_section_end(lines, ext)
-
- # Remove duplicates and already-present imports
- existing_imports = set()
- for i, line in enumerate(lines[:import_end_line]):
- stripped = line.strip()
- if self._is_import_line(stripped, ext):
- existing_imports.add(stripped)
-
- new_imports = [
- imp
- for imp in imports_to_add
- if imp not in existing_imports and imp not in imports_to_remove
- ]
-
- # Remove imports that should be removed
- result_lines = []
- for line in lines:
- if line.strip() not in imports_to_remove:
- result_lines.append(line)
-
- # Insert new imports at the import section end
- if new_imports:
- # Find insert position in result_lines
- insert_pos = self._find_import_section_end(result_lines, ext)
- for imp in reversed(new_imports):
- result_lines.insert(insert_pos, imp)
-
- merged_content = "\n".join(result_lines)
-
- return MergeResult(
- decision=MergeDecision.AUTO_MERGED,
- file_path=context.file_path,
- merged_content=merged_content,
- conflicts_resolved=[context.conflict],
- explanation=f"Combined {len(new_imports)} imports from {len(context.task_snapshots)} tasks",
- )
-
- def _merge_hooks_first(self, context: MergeContext) -> MergeResult:
- """Add hooks at function start, then apply other changes."""
- content = context.baseline_content
-
- # Collect hooks and other changes
- hooks: list[str] = []
- other_changes: list[SemanticChange] = []
-
- for snapshot in context.task_snapshots:
- for change in snapshot.semantic_changes:
- if change.change_type == ChangeType.ADD_HOOK_CALL:
- # Extract just the hook call from the change
- hook_content = self._extract_hook_call(change)
- if hook_content:
- hooks.append(hook_content)
- else:
- other_changes.append(change)
-
- # Find the function to modify
- func_location = context.conflict.location
- if func_location.startswith("function:"):
- func_name = func_location.split(":")[1]
- content = self._insert_hooks_into_function(content, func_name, hooks)
-
- # Apply other changes (simplified - just take the latest version)
- for change in other_changes:
- if change.content_after:
- # This is a simplification - in production we'd need smarter merging
- pass
-
- return MergeResult(
- decision=MergeDecision.AUTO_MERGED,
- file_path=context.file_path,
- merged_content=content,
- conflicts_resolved=[context.conflict],
- explanation=f"Added {len(hooks)} hooks to function start",
- )
-
- def _merge_hooks_then_wrap(self, context: MergeContext) -> MergeResult:
- """Add hooks first, then wrap JSX return."""
- content = context.baseline_content
-
- hooks: list[str] = []
- wraps: list[tuple[str, str]] = [] # (wrapper_component, props)
-
- for snapshot in context.task_snapshots:
- for change in snapshot.semantic_changes:
- if change.change_type == ChangeType.ADD_HOOK_CALL:
- hook_content = self._extract_hook_call(change)
- if hook_content:
- hooks.append(hook_content)
- elif change.change_type == ChangeType.WRAP_JSX:
- wrapper = self._extract_jsx_wrapper(change)
- if wrapper:
- wraps.append(wrapper)
-
- # Get function name from conflict location
- func_location = context.conflict.location
- if func_location.startswith("function:"):
- func_name = func_location.split(":")[1]
-
- # First add hooks
- if hooks:
- content = self._insert_hooks_into_function(content, func_name, hooks)
-
- # Then apply wraps
- for wrapper_name, wrapper_props in wraps:
- content = self._wrap_function_return(
- content, func_name, wrapper_name, wrapper_props
- )
-
- return MergeResult(
- decision=MergeDecision.AUTO_MERGED,
- file_path=context.file_path,
- merged_content=content,
- conflicts_resolved=[context.conflict],
- explanation=f"Added {len(hooks)} hooks and {len(wraps)} JSX wrappers",
- )
-
- def _merge_append_functions(self, context: MergeContext) -> MergeResult:
- """Append new functions to the file."""
- content = context.baseline_content
-
- # Collect all new functions
- new_functions: list[str] = []
-
- for snapshot in context.task_snapshots:
- for change in snapshot.semantic_changes:
- if (
- change.change_type == ChangeType.ADD_FUNCTION
- and change.content_after
- ):
- new_functions.append(change.content_after)
-
- # Append at the end (before any module.exports in JS)
- ext = Path(context.file_path).suffix.lower()
- insert_pos = self._find_function_insert_position(content, ext)
-
- if insert_pos is not None:
- lines = content.split("\n")
- for func in new_functions:
- lines.insert(insert_pos, "")
- lines.insert(insert_pos + 1, func)
- insert_pos += 2 + func.count("\n")
- content = "\n".join(lines)
- else:
- # Just append at the end
- for func in new_functions:
- content += f"\n\n{func}"
-
- return MergeResult(
- decision=MergeDecision.AUTO_MERGED,
- file_path=context.file_path,
- merged_content=content,
- conflicts_resolved=[context.conflict],
- explanation=f"Appended {len(new_functions)} new functions",
- )
-
- def _merge_append_methods(self, context: MergeContext) -> MergeResult:
- """Append new methods to a class."""
- content = context.baseline_content
-
- # Collect new methods by class
- new_methods: dict[str, list[str]] = {}
-
- for snapshot in context.task_snapshots:
- for change in snapshot.semantic_changes:
- if change.change_type == ChangeType.ADD_METHOD and change.content_after:
- # Extract class name from location
- class_name = (
- change.target.split(".")[0] if "." in change.target else None
- )
- if class_name:
- if class_name not in new_methods:
- new_methods[class_name] = []
- new_methods[class_name].append(change.content_after)
-
- # Insert methods into their classes
- for class_name, methods in new_methods.items():
- content = self._insert_methods_into_class(content, class_name, methods)
-
- total_methods = sum(len(m) for m in new_methods.values())
- return MergeResult(
- decision=MergeDecision.AUTO_MERGED,
- file_path=context.file_path,
- merged_content=content,
- conflicts_resolved=[context.conflict],
- explanation=f"Added {total_methods} methods to {len(new_methods)} classes",
- )
-
- def _merge_combine_props(self, context: MergeContext) -> MergeResult:
- """Combine JSX/object props from multiple changes."""
- # This is a simplified implementation
- # In production, we'd parse the JSX properly
-
- content = context.baseline_content
-
- # Collect all prop additions
- props_to_add: list[tuple[str, str]] = [] # (prop_name, prop_value)
-
- for snapshot in context.task_snapshots:
- for change in snapshot.semantic_changes:
- if change.change_type == ChangeType.MODIFY_JSX_PROPS:
- new_props = self._extract_new_props(change)
- props_to_add.extend(new_props)
-
- # For now, return the last version with all props
- # A proper implementation would merge prop objects
- if context.task_snapshots and context.task_snapshots[-1].semantic_changes:
- last_change = context.task_snapshots[-1].semantic_changes[-1]
- if last_change.content_after:
- content = self._apply_content_change(
- content, last_change.content_before, last_change.content_after
- )
-
- return MergeResult(
- decision=MergeDecision.AUTO_MERGED,
- file_path=context.file_path,
- merged_content=content,
- conflicts_resolved=[context.conflict],
- explanation=f"Combined props from {len(context.task_snapshots)} tasks",
- )
-
- def _merge_order_by_dependency(self, context: MergeContext) -> MergeResult:
- """Order changes by dependency analysis."""
- # Analyze dependencies between changes
- ordered_changes = self._topological_sort_changes(context.task_snapshots)
-
- content = context.baseline_content
-
- # Apply changes in dependency order
- for change in ordered_changes:
- if change.content_after:
- if change.change_type == ChangeType.ADD_HOOK_CALL:
- func_name = (
- change.target.split(".")[-1]
- if "." in change.target
- else change.target
- )
- hook_call = self._extract_hook_call(change)
- if hook_call:
- content = self._insert_hooks_into_function(
- content, func_name, [hook_call]
- )
- elif change.change_type == ChangeType.WRAP_JSX:
- wrapper = self._extract_jsx_wrapper(change)
- if wrapper:
- func_name = (
- change.target.split(".")[-1]
- if "." in change.target
- else change.target
- )
- content = self._wrap_function_return(
- content, func_name, wrapper[0], wrapper[1]
- )
-
- return MergeResult(
- decision=MergeDecision.AUTO_MERGED,
- file_path=context.file_path,
- merged_content=content,
- conflicts_resolved=[context.conflict],
- explanation="Changes applied in dependency order",
- )
-
- def _merge_order_by_time(self, context: MergeContext) -> MergeResult:
- """Apply changes in chronological order."""
- # Sort snapshots by start time
- sorted_snapshots = sorted(context.task_snapshots, key=lambda s: s.started_at)
-
- content = context.baseline_content
-
- # Apply each snapshot's changes in order
- for snapshot in sorted_snapshots:
- for change in snapshot.semantic_changes:
- if change.content_before and change.content_after:
- content = self._apply_content_change(
- content, change.content_before, change.content_after
- )
- elif change.content_after and not change.content_before:
- # Addition - handled by other strategies
- pass
-
- return MergeResult(
- decision=MergeDecision.AUTO_MERGED,
- file_path=context.file_path,
- merged_content=content,
- conflicts_resolved=[context.conflict],
- explanation=f"Applied {len(sorted_snapshots)} changes in chronological order",
- )
-
- def _merge_append_statements(self, context: MergeContext) -> MergeResult:
- """Append statements (variables, comments, etc.)."""
- content = context.baseline_content
-
- additions: list[str] = []
-
- for snapshot in context.task_snapshots:
- for change in snapshot.semantic_changes:
- if change.is_additive and change.content_after:
- additions.append(change.content_after)
-
- # Append at appropriate location
- for addition in additions:
- content += f"\n{addition}"
-
- return MergeResult(
- decision=MergeDecision.AUTO_MERGED,
- file_path=context.file_path,
- merged_content=content,
- conflicts_resolved=[context.conflict],
- explanation=f"Appended {len(additions)} statements",
- )
-
- # ========================================
- # Helper Methods
- # ========================================
-
- def _find_import_section_end(self, lines: list[str], ext: str) -> int:
- """Find where the import section ends."""
- last_import_line = 0
-
- for i, line in enumerate(lines):
- stripped = line.strip()
- if self._is_import_line(stripped, ext):
- last_import_line = i + 1
- elif (
- stripped
- and not stripped.startswith("#")
- and not stripped.startswith("//")
- ):
- # Non-empty, non-comment line after imports
- if last_import_line > 0:
- break
-
- return last_import_line if last_import_line > 0 else 0
-
- def _is_import_line(self, line: str, ext: str) -> bool:
- """Check if a line is an import statement."""
- if ext == ".py":
- return line.startswith("import ") or line.startswith("from ")
- elif ext in {".js", ".jsx", ".ts", ".tsx"}:
- return line.startswith("import ") or line.startswith("export ")
- return False
-
- def _extract_hook_call(self, change: SemanticChange) -> str | None:
- """Extract the hook call from a change."""
- if change.content_after:
- # Look for useXxx() pattern
- match = re.search(
- r"(const\s+\{[^}]+\}\s*=\s*)?use\w+\([^)]*\);?", change.content_after
- )
- if match:
- return match.group(0)
-
- # Also check for simple hook calls
- match = re.search(r"use\w+\([^)]*\);?", change.content_after)
- if match:
- return match.group(0)
-
- return None
-
- def _extract_jsx_wrapper(self, change: SemanticChange) -> tuple[str, str] | None:
- """Extract JSX wrapper component and props."""
- if change.content_after:
- # Look for
- match = re.search(r"<(\w+)([^>]*)>", change.content_after)
- if match:
- return (match.group(1), match.group(2).strip())
- return None
-
- def _insert_hooks_into_function(
- self,
- content: str,
- func_name: str,
- hooks: list[str],
- ) -> str:
- """Insert hooks at the start of a function."""
- # Find function and insert hooks after opening brace
- patterns = [
- # function Component() {
- rf"(function\s+{re.escape(func_name)}\s*\([^)]*\)\s*\{{)",
- # const Component = () => {
- rf"((?:const|let|var)\s+{re.escape(func_name)}\s*=\s*(?:async\s+)?(?:\([^)]*\)|[^=]+)\s*=>\s*\{{)",
- # const Component = function() {
- rf"((?:const|let|var)\s+{re.escape(func_name)}\s*=\s*function\s*\([^)]*\)\s*\{{)",
- ]
-
- for pattern in patterns:
- match = re.search(pattern, content)
- if match:
- insert_pos = match.end()
- hook_text = "\n " + "\n ".join(hooks)
- content = content[:insert_pos] + hook_text + content[insert_pos:]
- break
-
- return content
-
- def _wrap_function_return(
- self,
- content: str,
- func_name: str,
- wrapper_name: str,
- wrapper_props: str,
- ) -> str:
- """Wrap the return statement of a function in a JSX component."""
- # This is simplified - a real implementation would use AST
-
- # Find return statement with JSX
- return_pattern = r"(return\s*\(\s*)(<[^>]+>)"
-
- def replacer(match):
- return_start = match.group(1)
- jsx_start = match.group(2)
- props = f" {wrapper_props}" if wrapper_props else ""
- return f"{return_start}<{wrapper_name}{props}>\n {jsx_start}"
-
- content = re.sub(return_pattern, replacer, content, count=1)
-
- # Also need to close the wrapper - this is tricky without proper parsing
- # For now, we'll rely on the AI resolver for complex cases
-
- return content
-
- def _find_function_insert_position(self, content: str, ext: str) -> int | None:
- """Find the best position to insert new functions."""
- lines = content.split("\n")
-
- # Look for module.exports or export default at the end
- for i in range(len(lines) - 1, -1, -1):
- line = lines[i].strip()
- if line.startswith("module.exports") or line.startswith("export default"):
- return i
-
- return None
-
- def _insert_methods_into_class(
- self,
- content: str,
- class_name: str,
- methods: list[str],
- ) -> str:
- """Insert methods into a class body."""
- # Find class closing brace
- class_pattern = rf"class\s+{re.escape(class_name)}\s*(?:extends\s+\w+)?\s*\{{"
-
- match = re.search(class_pattern, content)
- if match:
- # Find the matching closing brace
- start = match.end()
- brace_count = 1
- pos = start
-
- while pos < len(content) and brace_count > 0:
- if content[pos] == "{":
- brace_count += 1
- elif content[pos] == "}":
- brace_count -= 1
- pos += 1
-
- if brace_count == 0:
- # Insert before closing brace
- insert_pos = pos - 1
- method_text = "\n\n " + "\n\n ".join(methods)
- content = content[:insert_pos] + method_text + content[insert_pos:]
-
- return content
-
- def _extract_new_props(self, change: SemanticChange) -> list[tuple[str, str]]:
- """Extract newly added props from a change."""
- props = []
- if change.content_after and change.content_before:
- # Simple diff - find props in after that aren't in before
- after_props = re.findall(r"(\w+)=\{([^}]+)\}", change.content_after)
- before_props = dict(re.findall(r"(\w+)=\{([^}]+)\}", change.content_before))
-
- for name, value in after_props:
- if name not in before_props:
- props.append((name, value))
-
- return props
-
- def _apply_content_change(
- self,
- content: str,
- old: str | None,
- new: str,
- ) -> str:
- """Apply a content change by replacing old with new."""
- if old and old in content:
- return content.replace(old, new, 1)
- return content
-
- def _topological_sort_changes(
- self,
- snapshots: list[TaskSnapshot],
- ) -> list[SemanticChange]:
- """Sort changes by their dependencies."""
- # Collect all changes
- all_changes: list[SemanticChange] = []
- for snapshot in snapshots:
- all_changes.extend(snapshot.semantic_changes)
-
- # Simple ordering: hooks before wraps before modifications
- priority = {
- ChangeType.ADD_IMPORT: 0,
- ChangeType.ADD_HOOK_CALL: 1,
- ChangeType.ADD_VARIABLE: 2,
- ChangeType.ADD_CONSTANT: 2,
- ChangeType.WRAP_JSX: 3,
- ChangeType.ADD_JSX_ELEMENT: 4,
- ChangeType.MODIFY_FUNCTION: 5,
- ChangeType.MODIFY_JSX_PROPS: 5,
- }
-
- return sorted(all_changes, key=lambda c: priority.get(c.change_type, 10))
diff --git a/auto-claude/progress.py b/auto-claude/progress.py
deleted file mode 100644
index e38cf2b3..00000000
--- a/auto-claude/progress.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""Backward compatibility shim - import from core.progress instead."""
-
-from core.progress import * # noqa: F403
diff --git a/auto-claude/prompts/_archived_ideation_high_value.md b/auto-claude/prompts/_archived_ideation_high_value.md
deleted file mode 100644
index 4c29cf47..00000000
--- a/auto-claude/prompts/_archived_ideation_high_value.md
+++ /dev/null
@@ -1,428 +0,0 @@
-## YOUR ROLE - HIGH-VALUE FEATURES IDEATION AGENT
-
-You are the **High-Value Features Ideation Agent** in the Auto-Build framework. Your job is to identify strategic features that would provide significant value to the target users, considering the project's purpose, audience, and competitive landscape.
-
-**Key Principle**: Think like a product manager. What features would make users love this product? What's missing that competitors have? What would create a "wow" moment?
-
----
-
-## YOUR CONTRACT
-
-**Input Files**:
-- `project_index.json` - Project structure and tech stack
-- `ideation_context.json` - Existing features, roadmap items, kanban tasks, target audience
-- `../roadmap/roadmap_discovery.json` (if exists) - Deep audience understanding
-- `../roadmap/roadmap.json` (if exists) - Existing planned features
-
-**Output**: Append to `ideation.json` with high-value feature ideas
-
-Each idea MUST have this structure:
-```json
-{
- "id": "hvf-001",
- "type": "high_value_features",
- "title": "Short descriptive title",
- "description": "What the feature does",
- "rationale": "Why this is high-value for users",
- "target_audience": "Who benefits most from this feature",
- "problem_solved": "What user problem this addresses",
- "value_proposition": "Why users would want this",
- "competitive_advantage": "How this differentiates from alternatives",
- "estimated_impact": "medium|high|critical",
- "complexity": "medium|high|complex",
- "dependencies": ["Required features or infrastructure"],
- "acceptance_criteria": ["Specific success criteria"],
- "status": "draft",
- "created_at": "ISO timestamp"
-}
-```
-
----
-
-## PHASE 0: DEEP CONTEXT LOADING
-
-```bash
-# Read project structure
-cat project_index.json
-
-# Read ideation context (critical for avoiding duplicates)
-cat ideation_context.json
-
-# Read roadmap discovery for audience understanding
-cat ../roadmap/roadmap_discovery.json 2>/dev/null || echo "No roadmap discovery - will need to infer audience"
-
-# Read existing roadmap to avoid duplicates
-cat ../roadmap/roadmap.json 2>/dev/null || echo "No existing roadmap"
-
-# Read README for product understanding
-cat README.md 2>/dev/null | head -100
-
-# Check for user feedback or feature requests
-cat docs/FEEDBACK.md 2>/dev/null || cat FEEDBACK.md 2>/dev/null || echo "No feedback file"
-cat docs/FEATURE_REQUESTS.md 2>/dev/null || echo "No feature requests file"
-ls -la .github/ISSUE_TEMPLATE* 2>/dev/null || echo "No issue templates"
-
-# Check for graph hints (historical insights from Graphiti)
-cat graph_hints.json 2>/dev/null || echo "No graph hints available"
-```
-
-Understand:
-- Who is the target audience?
-- What problem does the project solve?
-- What features already exist?
-- What is already planned (avoid duplicates)?
-- What have users asked for?
-- What historical insights are available from previous sessions?
-
-### Graph Hints Integration
-
-If `graph_hints.json` exists and contains hints for your ideation type (`high_value_features`), use them to:
-1. **Avoid duplicates**: Don't suggest features that have already been tried or rejected
-2. **Build on success**: Prioritize feature patterns that worked well in the past
-3. **Learn from failures**: Avoid approaches that previously caused issues
-4. **Leverage context**: Use historical knowledge to make better strategic suggestions
-
----
-
-## PHASE 1: UNDERSTAND THE VALUE LANDSCAPE
-
-### 1.1 Analyze Existing Features
-```bash
-# Map out current functionality
-grep -r "export.*function\|export.*component" --include="*.ts" --include="*.tsx" . | head -50
-
-# Find main user-facing features
-ls -la src/pages/ 2>/dev/null || ls -la src/routes/ 2>/dev/null || ls -la app/ 2>/dev/null
-
-# Check API capabilities
-ls -la src/api/ 2>/dev/null || ls -la api/ 2>/dev/null
-grep -r "router\.\|@app\.\|handler" --include="*.ts" --include="*.py" . | head -30
-```
-
-### 1.2 Understand User Journey
-Map the current user journey:
-1. How do users first interact with the product?
-2. What's the core action/value they get?
-3. What's the retention loop?
-4. Where do they likely drop off or get frustrated?
-
-### 1.3 Identify Feature Gaps
-Based on the project type, consider standard expected features:
-
-**For Web Apps:**
-- User authentication/authorization
-- Data export/import
-- Notifications
-- Sharing/collaboration
-- Search functionality
-- Analytics/insights
-- Settings/preferences
-- Mobile responsiveness
-
-**For CLI Tools:**
-- Configuration files
-- Output formatting options
-- Verbose/quiet modes
-- Plugin system
-- Shell completion
-- Progress indicators
-
-**For APIs:**
-- Rate limiting
-- Versioning
-- Documentation
-- Webhooks
-- Pagination
-- Filtering/sorting
-
----
-
-## PHASE 2: COMPETITIVE ANALYSIS
-
-Think about alternatives and what they offer:
-
-```
-
-Competitive Analysis:
-
-Project Type: [type from project_index]
-Problem Space: [what problem it solves]
-
-Likely Alternatives:
-1. [Alternative 1]
- - Key features they have: [list]
- - Their differentiation: [what makes them popular]
-
-2. [Alternative 2]
- - Key features they have: [list]
- - Their differentiation: [what makes them popular]
-
-Feature Gaps (things alternatives have that we don't):
-1. [Feature gap 1]
-2. [Feature gap 2]
-
-Opportunities for Differentiation:
-1. [Opportunity 1]
-2. [Opportunity 2]
-
-```
-
----
-
-## PHASE 3: USER NEED ANALYSIS
-
-For each potential feature area, analyze user needs:
-
-### A. Core Job-to-be-Done
-What is the user fundamentally trying to accomplish?
-What features would help them do this faster/better/easier?
-
-### B. Pain Point Relief
-What frustrations might users have?
-What features would eliminate these frustrations?
-
-### C. Delight Opportunities
-What would make users say "wow"?
-What unexpected value could we provide?
-
-### D. Workflow Integration
-How does this fit into users' existing workflows?
-What integrations would be valuable?
-
----
-
-## PHASE 4: STRATEGIC FEATURE IDEATION
-
-Generate ideas in these high-value categories:
-
-### Category 1: Must-Have Gaps
-Features that users expect but are missing:
-- Standard functionality for this type of product
-- Features that competitors all have
-- Basic capabilities that block adoption
-
-### Category 2: Retention Boosters
-Features that keep users coming back:
-- Saved preferences/state
-- Progress tracking
-- Notifications/reminders
-- Collaboration features
-
-### Category 3: Differentiation Features
-Features that make this unique:
-- Novel approaches to common problems
-- Unique combinations of capabilities
-- Specialized functionality for target audience
-
-### Category 4: Expansion Enablers
-Features that open new use cases:
-- Integrations with popular tools
-- API access for power users
-- Plugin/extension systems
-- White-label capabilities
-
-### Category 5: Value Multipliers
-Features that increase perceived value:
-- Analytics and insights
-- Automation capabilities
-- Bulk operations
-- Export/sharing
-
----
-
-## PHASE 5: DEEP FEATURE ANALYSIS
-
-For each promising feature, use ultrathink for deep analysis:
-
-```
-
-High-Value Feature Analysis: [Feature Title]
-
-TARGET AUDIENCE
-- Primary beneficiaries: [who]
-- Secondary beneficiaries: [who]
-- Usage scenario: [when/how they'd use it]
-
-PROBLEM SOLVED
-- User pain point: [specific problem]
-- Current workaround: [how they solve it now]
-- Cost of current approach: [time/money/frustration]
-
-VALUE PROPOSITION
-- Primary benefit: [main value]
-- Secondary benefits: [additional value]
-- Emotional benefit: [how it makes them feel]
-
-COMPETITIVE CONTEXT
-- Do alternatives have this? [yes/no/partially]
-- Our unique angle: [differentiation]
-- Barrier to switching: [if they want this, why choose us]
-
-IMPLEMENTATION CONSIDERATIONS
-- Dependencies: [what's needed first]
-- Complexity: [medium/high/complex]
-- Risk factors: [potential issues]
-
-ACCEPTANCE CRITERIA (specific and measurable)
-1. [Criterion 1]
-2. [Criterion 2]
-3. [Criterion 3]
-
-IMPACT ASSESSMENT
-- User impact: [low/medium/high/critical]
-- Business impact: [low/medium/high/critical]
-- Technical risk: [low/medium/high]
-
-```
-
----
-
-## PHASE 6: PRIORITIZE BY VALUE
-
-Evaluate each idea against:
-
-1. **Impact**: How much would this improve user outcomes?
- - Critical: Transforms user capability
- - High: Significantly improves experience
- - Medium: Notable improvement
-
-2. **Demand**: How much do users want this?
- - Explicit requests from users
- - Standard expectation for product type
- - Nice-to-have enhancement
-
-3. **Differentiation**: Does this set us apart?
- - Unique capability
- - Better implementation than alternatives
- - Table stakes (needed to compete)
-
-4. **Feasibility**: Can we build this well?
- - Complexity assessment
- - Dependencies required
- - Team capability match
-
----
-
-## PHASE 7: CREATE/UPDATE IDEATION.JSON (MANDATORY)
-
-**You MUST create or update ideation.json with your ideas.**
-
-```bash
-# Check if file exists
-if [ -f ideation.json ]; then
- cat ideation.json
-fi
-```
-
-Create the high-value features structure:
-
-```bash
-cat > high_value_ideas.json << 'EOF'
-{
- "high_value_features": [
- {
- "id": "hvf-001",
- "type": "high_value_features",
- "title": "[Feature Title]",
- "description": "[What the feature does]",
- "rationale": "[Why this is high-value]",
- "target_audience": "[Who benefits most]",
- "problem_solved": "[User problem addressed]",
- "value_proposition": "[Why users want this]",
- "competitive_advantage": "[Differentiation]",
- "estimated_impact": "[medium|high|critical]",
- "complexity": "[medium|high|complex]",
- "dependencies": ["[Dependency 1]"],
- "acceptance_criteria": [
- "[Criterion 1]",
- "[Criterion 2]",
- "[Criterion 3]"
- ],
- "status": "draft",
- "created_at": "[ISO timestamp]"
- }
- ]
-}
-EOF
-```
-
-Verify:
-```bash
-cat high_value_ideas.json
-```
-
----
-
-## VALIDATION
-
-After creating ideas:
-
-1. Is it valid JSON?
-2. Does each idea have a unique id starting with "hvf-"?
-3. Does each idea have target_audience, problem_solved, and value_proposition?
-4. Does each idea have at least 3 acceptance_criteria?
-5. Is estimated_impact justified by the analysis?
-
----
-
-## COMPLETION
-
-Signal completion:
-
-```
-=== HIGH-VALUE FEATURES IDEATION COMPLETE ===
-
-Ideas Generated: [count]
-
-Summary by Impact:
-- Critical: [count]
-- High: [count]
-- Medium: [count]
-
-Top Recommendations:
-1. [Title] - [impact] impact - [brief rationale]
-2. [Title] - [impact] impact - [brief rationale]
-3. [Title] - [impact] impact - [brief rationale]
-
-high_value_ideas.json created successfully.
-
-Next phase: Complete or Merge
-```
-
----
-
-## CRITICAL RULES
-
-1. **AVOID DUPLICATES** - Check ideation_context.json and roadmap thoroughly
-2. **BE STRATEGIC** - Focus on features that move the needle, not incremental improvements
-3. **JUSTIFY IMPACT** - Every "high" or "critical" rating needs clear rationale
-4. **CONSIDER DEPENDENCIES** - Note what needs to exist first
-5. **THINK LIKE A USER** - What would make them choose this over alternatives?
-6. **BE SPECIFIC** - Concrete features, not vague directions like "improve performance"
-
----
-
-## EXAMPLES OF GOOD HIGH-VALUE FEATURES
-
-**For a social media scheduler:**
-- "AI-powered optimal posting time suggestions" (solves real pain, clear value)
-- "Team collaboration with approval workflows" (unlocks business users)
-- "Analytics dashboard with ROI metrics" (proves value, increases retention)
-
-**For a developer tool:**
-- "GitHub/GitLab integration for automatic sync" (workflow integration)
-- "Team sharing with role-based permissions" (expands use case)
-- "Custom templates and presets" (power user retention)
-
-## EXAMPLES OF BAD HIGH-VALUE FEATURES
-
-- "Make it faster" (too vague)
-- "Add dark mode" (nice but not high-value unless accessibility focused)
-- "Fix bugs" (not a feature)
-- "Add AI" (no clear use case)
-
----
-
-## BEGIN
-
-Start by deeply understanding the project context, target audience, and existing features, then generate strategic feature ideas.
diff --git a/auto-claude/prompts/_archived_ideation_low_hanging_fruit.md b/auto-claude/prompts/_archived_ideation_low_hanging_fruit.md
deleted file mode 100644
index 26f6b1c8..00000000
--- a/auto-claude/prompts/_archived_ideation_low_hanging_fruit.md
+++ /dev/null
@@ -1,315 +0,0 @@
-## YOUR ROLE - LOW-HANGING FRUIT IDEATION AGENT
-
-You are the **Low-Hanging Fruit Ideation Agent** in the Auto-Build framework. Your job is to identify quick-win feature ideas that build naturally upon the existing codebase patterns and features.
-
-**Key Principle**: Find opportunities to add value with minimal disruption. These are features that "almost write themselves" because the patterns and infrastructure already exist.
-
----
-
-## YOUR CONTRACT
-
-**Input Files**:
-- `project_index.json` - Project structure and tech stack
-- `ideation_context.json` - Existing features, roadmap items, kanban tasks
-- `memory/codebase_map.json` (if exists) - Previously discovered file purposes
-- `memory/patterns.md` (if exists) - Established code patterns
-
-**Output**: Append to `ideation.json` with low-hanging fruit ideas
-
-Each idea MUST have this structure:
-```json
-{
- "id": "lhf-001",
- "type": "low_hanging_fruit",
- "title": "Short descriptive title",
- "description": "What the feature does",
- "rationale": "Why this is low-hanging fruit - what patterns it extends",
- "builds_upon": ["Feature/pattern it extends"],
- "estimated_effort": "trivial|small|medium",
- "affected_files": ["file1.ts", "file2.ts"],
- "existing_patterns": ["Pattern to follow"],
- "status": "draft",
- "created_at": "ISO timestamp"
-}
-```
-
----
-
-## PHASE 0: LOAD CONTEXT
-
-```bash
-# Read project structure
-cat project_index.json
-
-# Read ideation context (existing features, planned items)
-cat ideation_context.json
-
-# Check for memory files
-cat memory/codebase_map.json 2>/dev/null || echo "No codebase map yet"
-cat memory/patterns.md 2>/dev/null || echo "No patterns documented"
-
-# Look at existing roadmap if available
-cat ../roadmap/roadmap.json 2>/dev/null | head -100 || echo "No roadmap"
-
-# Check for graph hints (historical insights from Graphiti)
-cat graph_hints.json 2>/dev/null || echo "No graph hints available"
-```
-
-Understand:
-- What is the project about?
-- What features already exist?
-- What patterns are established?
-- What is already planned (to avoid duplicates)?
-- What historical insights are available from previous sessions?
-
-### Graph Hints Integration
-
-If `graph_hints.json` exists and contains hints for your ideation type (`low_hanging_fruit`), use them to:
-1. **Avoid duplicates**: Don't suggest ideas that have already been tried or rejected
-2. **Build on success**: Prioritize patterns that worked well in the past
-3. **Learn from failures**: Avoid approaches that previously caused issues
-4. **Leverage context**: Use historical file/pattern knowledge to make better suggestions
-
----
-
-## PHASE 1: DISCOVER EXISTING PATTERNS
-
-Search for patterns that could be extended:
-
-```bash
-# Find similar components/modules that could be replicated
-grep -r "export function\|export const\|export class" --include="*.ts" --include="*.tsx" . | head -40
-
-# Find existing API routes/endpoints
-grep -r "router\.\|app\.\|api/\|/api" --include="*.ts" --include="*.py" . | head -30
-
-# Find existing UI components
-ls -la src/components/ 2>/dev/null || ls -la components/ 2>/dev/null
-
-# Find utility functions that could have more uses
-grep -r "export.*util\|export.*helper\|export.*format" --include="*.ts" . | head -20
-
-# Find existing CRUD operations
-grep -r "create\|update\|delete\|get\|list" --include="*.ts" --include="*.py" . | head -30
-```
-
-Look for:
-- Patterns that are repeated (could be extended)
-- Features that handle one case but could handle more
-- Utilities that could have additional methods
-- UI components that could have variants
-
----
-
-## PHASE 2: IDENTIFY LOW-HANGING FRUIT CATEGORIES
-
-Think about these opportunity categories:
-
-### A. Pattern Extensions
-- Existing CRUD for one entity -> CRUD for similar entity
-- Existing filter for one field -> Filters for more fields
-- Existing sort by one column -> Sort by multiple columns
-- Existing export to CSV -> Export to JSON/Excel
-
-### B. Configuration/Settings
-- Hard-coded values that could be user-configurable
-- Missing user preferences that follow existing preference patterns
-- Feature toggles that extend existing toggle patterns
-
-### C. Utility Additions
-- Existing validators that could validate more cases
-- Existing formatters that could handle more formats
-- Existing helpers that could have related helpers
-
-### D. UI Enhancements
-- Missing loading states that follow existing loading patterns
-- Missing empty states that follow existing empty state patterns
-- Missing error states that follow existing error patterns
-- Keyboard shortcuts that extend existing shortcut patterns
-
-### E. Data Handling
-- Existing list views that could have pagination (if pattern exists)
-- Existing forms that could have auto-save (if pattern exists)
-- Existing data that could have search (if pattern exists)
-
----
-
-## PHASE 3: ANALYZE SPECIFIC OPPORTUNITIES
-
-For each promising opportunity found:
-
-```bash
-# Examine the pattern file closely
-cat [file_path] | head -100
-
-# See how it's used
-grep -r "[function_name]\|[component_name]" --include="*.ts" --include="*.tsx" . | head -10
-
-# Check for related implementations
-ls -la $(dirname [file_path])
-```
-
-Rate each opportunity:
-- **Trivial** (1-2 hours): Direct copy with minor changes
-- **Small** (half day): Clear pattern to follow, some new logic
-- **Medium** (1 day): Pattern exists but needs adaptation
-
----
-
-## PHASE 4: FILTER AND PRIORITIZE
-
-For each idea, verify:
-
-1. **Not Already Planned**: Check ideation_context.json for similar items
-2. **Pattern Exists**: The code pattern is already in the codebase
-3. **Infrastructure Ready**: No new dependencies or major setup needed
-4. **Clear Value**: It provides obvious user benefit
-
-Discard ideas that:
-- Require new architectural patterns
-- Need external service integration
-- Require significant research
-- Are already in roadmap or kanban
-
----
-
-## PHASE 5: GENERATE IDEAS (MANDATORY)
-
-Generate 3-5 concrete low-hanging fruit ideas.
-
-For each idea, use ultrathink to deeply analyze:
-
-```
-
-Analyzing potential low-hanging fruit: [title]
-
-Existing pattern found in: [file_path]
-Pattern summary: [how it works]
-
-Extension opportunity:
-- What exactly would be added/changed?
-- What files would be affected?
-- What existing code can be reused?
-
-Effort estimation:
-- Lines of code estimate: [number]
-- Test changes needed: [description]
-- Risk level: [low/medium]
-
-Why this is truly low-hanging fruit:
-- [reason 1]
-- [reason 2]
-
-```
-
----
-
-## PHASE 6: CREATE/UPDATE IDEATION.JSON (MANDATORY)
-
-**You MUST create or update ideation.json with your ideas.**
-
-If ideation.json exists, read it first and append:
-
-```bash
-# Check if file exists
-if [ -f ideation.json ]; then
- cat ideation.json
- # Will need to merge ideas
-fi
-```
-
-Create the ideas structure:
-
-```bash
-cat > low_hanging_fruit_ideas.json << 'EOF'
-{
- "low_hanging_fruit": [
- {
- "id": "lhf-001",
- "type": "low_hanging_fruit",
- "title": "[Title]",
- "description": "[What it does]",
- "rationale": "[Why it's low-hanging fruit]",
- "builds_upon": ["[Existing feature/pattern]"],
- "estimated_effort": "[trivial|small|medium]",
- "affected_files": ["[file1.ts]", "[file2.ts]"],
- "existing_patterns": ["[Pattern to follow]"],
- "status": "draft",
- "created_at": "[ISO timestamp]"
- }
- ]
-}
-EOF
-```
-
-Verify:
-```bash
-cat low_hanging_fruit_ideas.json
-```
-
----
-
-## VALIDATION
-
-After creating ideas:
-
-1. Is it valid JSON?
-2. Does each idea have a unique id starting with "lhf-"?
-3. Does each idea have builds_upon with at least one item?
-4. Does each idea have affected_files listing real files?
-5. Does each idea have existing_patterns?
-
----
-
-## COMPLETION
-
-Signal completion:
-
-```
-=== LOW-HANGING FRUIT IDEATION COMPLETE ===
-
-Ideas Generated: [count]
-
-Summary:
-1. [title] - [effort] - builds on [pattern]
-2. [title] - [effort] - builds on [pattern]
-...
-
-low_hanging_fruit_ideas.json created successfully.
-
-Next phase: [UI/UX or High-Value or Complete]
-```
-
----
-
-## CRITICAL RULES
-
-1. **ONLY suggest ideas with existing patterns** - If the pattern doesn't exist, it's not low-hanging fruit
-2. **Be specific about affected files** - List the actual files that would change
-3. **Reference real patterns** - Point to actual code in the codebase
-4. **Avoid duplicates** - Check ideation_context.json first
-5. **Keep effort realistic** - If it requires research, it's not low-hanging fruit
-6. **Focus on incremental value** - Small improvements that compound
-
----
-
-## EXAMPLES OF GOOD LOW-HANGING FRUIT
-
-- "Add search to user list" (when search exists in product list)
-- "Add keyboard shortcut for save" (when other shortcuts exist)
-- "Add CSV export" (when JSON export exists)
-- "Add dark mode to settings modal" (when dark mode exists elsewhere)
-- "Add pagination to comments" (when pagination exists for posts)
-
-## EXAMPLES OF BAD LOW-HANGING FRUIT (NOT ACTUALLY LOW-HANGING)
-
-- "Add real-time updates" (needs WebSocket infrastructure)
-- "Add AI-powered suggestions" (needs ML integration)
-- "Add multi-language support" (needs i18n architecture)
-- "Add offline mode" (needs service worker setup)
-
----
-
-## BEGIN
-
-Start by reading project_index.json and ideation_context.json, then search for patterns and opportunities.
diff --git a/auto-claude/runners/ai_analyzer/REFACTORING.md b/auto-claude/runners/ai_analyzer/REFACTORING.md
deleted file mode 100644
index 912b6a6c..00000000
--- a/auto-claude/runners/ai_analyzer/REFACTORING.md
+++ /dev/null
@@ -1,284 +0,0 @@
-# AI Analyzer Refactoring Report
-
-## Executive Summary
-
-Successfully refactored `ai_analyzer_runner.py` from a monolithic 650-line file into a well-structured, modular package with 9 focused components.
-
-## Metrics
-
-| Metric | Before | After | Improvement |
-|--------|--------|-------|-------------|
-| Entry Point Size | 650 lines | 86 lines | 87% reduction |
-| Number of Files | 1 | 10 | Better organization |
-| Largest Module | 650 lines | 312 lines | 52% reduction |
-| Type Hints | Partial | Comprehensive | 100% coverage |
-| Test Isolation | Poor | Excellent | Modular design |
-
-## Module Breakdown
-
-### 1. `__init__.py` (10 lines)
-- Package initialization
-- Public API exports
-- Clean entry point for imports
-
-### 2. `models.py` (89 lines)
-**Responsibility**: Data models and type definitions
-
-**Exports**:
-- `AnalyzerType` enum
-- `CostEstimate` dataclass
-- `AnalysisResult` dataclass
-- `Vulnerability`, `PerformanceBottleneck`, `CodeSmell` dataclasses
-
-**Benefits**:
-- Centralized type definitions
-- Type safety throughout the package
-- Easy to extend with new models
-
-### 3. `runner.py` (197 lines)
-**Responsibility**: Main orchestration
-
-**Exports**:
-- `AIAnalyzerRunner` class
-
-**Key Methods**:
-- `run_full_analysis()` - Orchestrates complete analysis
-- `_run_single_analyzer()` - Executes individual analyzer
-- `_calculate_overall_score()` - Aggregates scores
-- `print_summary()` - Delegates to SummaryPrinter
-
-**Benefits**:
-- Clear control flow
-- Coordinates all components
-- Single entry point for analysis
-
-### 4. `analyzers.py` (312 lines)
-**Responsibility**: Individual analyzer implementations
-
-**Exports**:
-- `BaseAnalyzer` - Abstract base class
-- 6 specific analyzers:
- - `CodeRelationshipsAnalyzer`
- - `BusinessLogicAnalyzer`
- - `ArchitectureAnalyzer`
- - `SecurityAnalyzer`
- - `PerformanceAnalyzer`
- - `CodeQualityAnalyzer`
-- `AnalyzerFactory` - Factory pattern implementation
-
-**Benefits**:
-- Each analyzer is self-contained
-- Easy to add new analyzers
-- Factory pattern simplifies creation
-- Prompts separated from execution logic
-
-### 5. `claude_client.py` (144 lines)
-**Responsibility**: Claude SDK integration
-
-**Exports**:
-- `ClaudeAnalysisClient` class
-- `CLAUDE_SDK_AVAILABLE` flag
-
-**Key Features**:
-- OAuth token validation
-- Security settings management
-- Response collection
-- Automatic cleanup
-
-**Benefits**:
-- Isolates SDK-specific code
-- Handles connection lifecycle
-- Graceful error handling
-
-### 6. `cost_estimator.py` (95 lines)
-**Responsibility**: API cost estimation
-
-**Exports**:
-- `CostEstimator` class
-
-**Key Features**:
-- Token estimation based on project size
-- Python file counting
-- Cost calculation
-- Configurable pricing
-
-**Benefits**:
-- Transparent cost visibility
-- Easy to update pricing
-- Excludes virtual environments
-
-### 7. `cache_manager.py` (61 lines)
-**Responsibility**: Result caching
-
-**Exports**:
-- `CacheManager` class
-
-**Key Features**:
-- 24-hour cache validity
-- Automatic directory creation
-- Cache age reporting
-- Skip cache option
-
-**Benefits**:
-- Reduces API costs
-- Faster repeated analyses
-- Configurable validity period
-
-### 8. `result_parser.py` (59 lines)
-**Responsibility**: JSON parsing
-
-**Exports**:
-- `ResultParser` class
-
-**Key Features**:
-- Multiple parsing strategies
-- Markdown code block extraction
-- Fallback to defaults
-- Error resilience
-
-**Benefits**:
-- Robust parsing
-- Handles various response formats
-- Never fails catastrophically
-
-### 9. `summary_printer.py` (97 lines)
-**Responsibility**: Output formatting
-
-**Exports**:
-- `SummaryPrinter` class
-
-**Key Features**:
-- Formatted score display
-- Security vulnerability summary
-- Performance bottleneck summary
-- Cost estimate display
-
-**Benefits**:
-- Consistent output format
-- Easy to modify presentation
-- Separated from business logic
-
-### 10. `ai_analyzer_runner.py` (86 lines)
-**Responsibility**: CLI entry point
-
-**Key Features**:
-- Argument parsing
-- Index file validation
-- Graceful import error handling
-- Async execution
-
-**Benefits**:
-- Clean separation of CLI and library
-- Minimal dependencies at entry point
-- Clear error messages
-
-## Design Patterns Applied
-
-1. **Factory Pattern**: `AnalyzerFactory` for creating analyzer instances
-2. **Strategy Pattern**: Different analyzers implement common interface
-3. **Single Responsibility**: Each module has one clear purpose
-4. **Dependency Injection**: Dependencies passed via constructors
-5. **Separation of Concerns**: UI, business logic, and data separated
-
-## Code Quality Improvements
-
-### Type Safety
-- Added comprehensive type hints to all functions
-- Used dataclasses for structured data
-- Enum for analyzer types
-
-### Error Handling
-- Graceful degradation with defaults
-- Clear error messages
-- Import error handling
-
-### Testability
-- Each module can be tested independently
-- Minimal coupling between components
-- Mock-friendly interfaces
-
-### Maintainability
-- Clear module boundaries
-- Self-documenting code structure
-- Comprehensive docstrings
-
-## Migration Guide
-
-### For External Code
-
-No changes required! The refactored code maintains 100% backward compatibility:
-
-```python
-# This still works exactly the same
-from ai_analyzer import AIAnalyzerRunner
-```
-
-### Adding New Analyzers
-
-Before (required modifying 650-line file):
-1. Add method to `AIAnalyzerRunner` class
-2. Update `_run_analyzer()` dispatcher
-3. Update analyzer list
-4. Hope you didn't break anything
-
-After (clear, focused changes):
-1. Create new class in `analyzers.py` extending `BaseAnalyzer`
-2. Add to `AnalyzerFactory.ANALYZER_CLASSES` (1 line)
-3. Add to `AnalyzerType` enum (1 line)
-4. Optional: Update summary printer
-
-## Testing Strategy
-
-Each module can now be tested independently:
-
-```python
-# Test cost estimator in isolation
-from ai_analyzer.cost_estimator import CostEstimator
-estimator = CostEstimator(project_dir, mock_index)
-assert estimator.estimate_cost().estimated_tokens > 0
-
-# Test cache manager
-from ai_analyzer.cache_manager import CacheManager
-cache = CacheManager(tmp_path)
-cache.save_result({"score": 85})
-assert cache.get_cached_result() is not None
-
-# Test analyzers
-from ai_analyzer.analyzers import SecurityAnalyzer
-analyzer = SecurityAnalyzer(mock_index)
-prompt = analyzer.get_prompt()
-assert "OWASP" in prompt
-```
-
-## Performance Impact
-
-- No performance degradation
-- Module loading is lazy (only imported when needed)
-- Cache management remains efficient
-- Same API call patterns
-
-## Future Enhancements
-
-The modular structure now makes these enhancements easy:
-
-1. **Parallel Analyzer Execution**: Run analyzers concurrently
-2. **Custom Analyzers**: Plugin system for external analyzers
-3. **Alternative Backends**: Support other LLMs besides Claude
-4. **Enhanced Caching**: Redis or database-backed caching
-5. **Progressive Results**: Stream results as analyzers complete
-6. **Detailed Logging**: Per-module logging configuration
-
-## Conclusion
-
-The refactoring achieved all goals:
-
-✅ **Reduced complexity**: Entry point 87% smaller
-✅ **Clear responsibilities**: Each module has single purpose
-✅ **Type safety**: Comprehensive type hints
-✅ **Maintainability**: Easy to locate and modify features
-✅ **Testability**: Modules can be tested independently
-✅ **Extensibility**: Simple to add new analyzers
-✅ **Documentation**: README and inline docs
-✅ **Zero breaking changes**: 100% backward compatible
-
-The codebase is now production-ready, maintainable, and professional.
diff --git a/auto-claude/spec/validate_pkg/MIGRATION.md b/auto-claude/spec/validate_pkg/MIGRATION.md
deleted file mode 100644
index 5441a22b..00000000
--- a/auto-claude/spec/validate_pkg/MIGRATION.md
+++ /dev/null
@@ -1,198 +0,0 @@
-# Migration Guide
-
-This document describes the changes made during the refactoring of `validate_spec.py` and how to update code that depends on it.
-
-## Summary of Changes
-
-The monolithic 633-line `validate_spec.py` file has been refactored into a modular package structure with:
-- Main entry point reduced from 633 to 109 lines (83% reduction)
-- 10 focused modules with clear responsibilities
-- Total package size: 784 lines (including extensive documentation)
-
-## File Structure
-
-### Before
-```
-auto-claude/
-└── validate_spec.py (633 lines)
-```
-
-### After
-```
-auto-claude/
-├── validate_spec.py (109 lines - entry point)
-└── validate_spec/
- ├── __init__.py
- ├── models.py
- ├── schemas.py
- ├── auto_fix.py
- ├── spec_validator.py
- ├── README.md
- ├── MIGRATION.md
- └── validators/
- ├── __init__.py
- ├── prereqs_validator.py
- ├── context_validator.py
- ├── spec_document_validator.py
- └── implementation_plan_validator.py
-```
-
-## Import Changes
-
-### SpecValidator
-
-**Before:**
-```python
-from validate_spec import SpecValidator
-```
-
-**After (option 1 - recommended):**
-```python
-from validate_spec import SpecValidator
-```
-
-**After (option 2 - explicit):**
-```python
-from validate_spec.spec_validator import SpecValidator
-```
-
-### ValidationResult
-
-**Before:**
-```python
-from validate_spec import ValidationResult
-```
-
-**After (option 1 - recommended):**
-```python
-from validate_spec import ValidationResult
-```
-
-**After (option 2 - explicit):**
-```python
-from validate_spec.models import ValidationResult
-```
-
-### auto_fix_plan
-
-**Before:**
-```python
-from validate_spec import auto_fix_plan
-```
-
-**After (option 1 - recommended):**
-```python
-from validate_spec import auto_fix_plan
-```
-
-**After (option 2 - explicit):**
-```python
-from validate_spec.auto_fix import auto_fix_plan
-```
-
-## Files Updated
-
-The following files have been updated to use the new import structure:
-
-### 1. `auto-claude/spec/phases/planning_phases.py`
-**Changed:**
-```python
-# Before
-from validate_spec import auto_fix_plan
-
-# After
-from validate_spec.auto_fix import auto_fix_plan
-```
-
-### 2. `auto-claude/spec/pipeline/orchestrator.py`
-**Changed:**
-```python
-# Before
-from validate_spec import SpecValidator
-
-# After
-from validate_spec.spec_validator import SpecValidator
-```
-
-## Backward Compatibility
-
-The package exports maintain backward compatibility through `__init__.py`:
-
-```python
-# validate_spec/__init__.py
-from .auto_fix import auto_fix_plan
-from .models import ValidationResult
-from .spec_validator import SpecValidator
-
-__all__ = ["SpecValidator", "ValidationResult", "auto_fix_plan"]
-```
-
-This means existing code using:
-```python
-from validate_spec import SpecValidator, ValidationResult, auto_fix_plan
-```
-
-Will continue to work without changes.
-
-## CLI Usage
-
-The CLI interface remains **completely unchanged**:
-
-```bash
-# All existing commands work exactly the same
-python auto-claude/validate_spec.py --spec-dir path/to/spec --checkpoint all
-python auto-claude/validate_spec.py --spec-dir path/to/spec --checkpoint context
-python auto-claude/validate_spec.py --spec-dir path/to/spec --auto-fix --checkpoint plan
-python auto-claude/validate_spec.py --spec-dir path/to/spec --checkpoint all --json
-```
-
-## Testing
-
-All existing functionality has been preserved:
-
-1. **Validation logic**: Identical behavior
-2. **Error messages**: Same format
-3. **Auto-fix**: Same functionality
-4. **CLI**: Same interface
-5. **JSON output**: Same structure
-
-## Benefits
-
-### Maintainability
-- Each validator is in its own file
-- Easy to locate and modify specific validation logic
-- Clear separation of concerns
-
-### Testability
-- Individual validators can be tested in isolation
-- Mock dependencies are easier to set up
-- Unit tests can focus on specific functionality
-
-### Extensibility
-- Adding new validators is straightforward
-- New validation rules can be added without touching existing code
-- Schema changes are centralized
-
-### Readability
-- Main entry point is now 109 lines instead of 633
-- Each file has a single, clear purpose
-- Documentation is embedded in each module
-
-## Rollback
-
-If needed, the original file is preserved as `validate_spec.py.backup`:
-
-```bash
-# To rollback
-cd auto-claude
-mv validate_spec.py validate_spec.py.refactored
-mv validate_spec.py.backup validate_spec.py
-rm -rf validate_spec/
-```
-
-## Questions?
-
-For questions or issues related to this refactoring:
-1. Check the [README.md](README.md) for usage examples
-2. Review the inline documentation in each module
-3. Compare with `validate_spec.py.backup` if needed
diff --git a/auto-claude/validate_spec/__init__.py b/auto-claude/validate_spec/__init__.py
deleted file mode 100644
index acd5d2d7..00000000
--- a/auto-claude/validate_spec/__init__.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"""
-Backward compatibility shim for validate_spec package.
-
-DEPRECATED: This package has been moved to spec.validate_pkg.
-
-Please update your imports:
- OLD: from validate_spec import SpecValidator, ValidationResult, auto_fix_plan
- NEW: from spec.validate_pkg import SpecValidator, ValidationResult, auto_fix_plan
-
-This shim provides compatibility but will be removed in a future version.
-"""
-
-import sys
-from pathlib import Path
-
-
-# Lazy import to avoid circular dependencies
-def __getattr__(name):
- """Lazy import mechanism to avoid circular imports."""
- if name in ("SpecValidator", "ValidationResult", "auto_fix_plan"):
- # Add spec directory to path temporarily to allow direct imports
- # without triggering spec.__init__
- spec_dir = Path(__file__).parent.parent / "spec"
- if str(spec_dir) not in sys.path:
- sys.path.insert(0, str(spec_dir))
-
- try:
- # Import directly from validate_pkg without going through spec package
- from validate_pkg import SpecValidator, ValidationResult, auto_fix_plan
-
- # Cache the imported values in this module
- globals()["SpecValidator"] = SpecValidator
- globals()["ValidationResult"] = ValidationResult
- globals()["auto_fix_plan"] = auto_fix_plan
-
- return globals()[name]
- finally:
- # Clean up path modification
- if str(spec_dir) in sys.path:
- sys.path.remove(str(spec_dir))
-
- raise AttributeError(f"module 'validate_spec' has no attribute '{name}'")
-
-
-__all__ = ["SpecValidator", "ValidationResult", "auto_fix_plan"]
diff --git a/auto-claude/validate_spec/auto_fix.py b/auto-claude/validate_spec/auto_fix.py
deleted file mode 100644
index d3b1660c..00000000
--- a/auto-claude/validate_spec/auto_fix.py
+++ /dev/null
@@ -1,39 +0,0 @@
-"""
-Backward compatibility shim for auto_fix module.
-
-DEPRECATED: This module has been moved to spec.validate_pkg.auto_fix.
-
-Please update your imports:
- OLD: from validate_spec.auto_fix import auto_fix_plan
- NEW: from spec.validate_pkg.auto_fix import auto_fix_plan
-
-This shim provides compatibility but will be removed in a future version.
-"""
-
-import sys
-from pathlib import Path
-
-
-# Lazy import to avoid circular dependencies
-def __getattr__(name):
- """Lazy import mechanism to avoid circular imports."""
- if name == "auto_fix_plan":
- # Add spec directory to path temporarily to allow direct imports
- # without triggering spec.__init__
- spec_dir = Path(__file__).parent.parent / "spec"
- if str(spec_dir) not in sys.path:
- sys.path.insert(0, str(spec_dir))
-
- try:
- # Import directly from validate_pkg without going through spec package
- from validate_pkg.auto_fix import auto_fix_plan
-
- # Cache the imported value in this module
- globals()["auto_fix_plan"] = auto_fix_plan
- return auto_fix_plan
- finally:
- # Clean up path modification
- if str(spec_dir) in sys.path:
- sys.path.remove(str(spec_dir))
-
- raise AttributeError(f"module 'validate_spec.auto_fix' has no attribute '{name}'")
diff --git a/auto-claude/validate_spec/spec_validator.py b/auto-claude/validate_spec/spec_validator.py
deleted file mode 100644
index a304d1ae..00000000
--- a/auto-claude/validate_spec/spec_validator.py
+++ /dev/null
@@ -1,41 +0,0 @@
-"""
-Backward compatibility shim for spec_validator module.
-
-DEPRECATED: This module has been moved to spec.validate_pkg.spec_validator.
-
-Please update your imports:
- OLD: from validate_spec.spec_validator import SpecValidator
- NEW: from spec.validate_pkg.spec_validator import SpecValidator
-
-This shim provides compatibility but will be removed in a future version.
-"""
-
-import sys
-from pathlib import Path
-
-
-# Lazy import to avoid circular dependencies
-def __getattr__(name):
- """Lazy import mechanism to avoid circular imports."""
- if name == "SpecValidator":
- # Add spec directory to path temporarily to allow direct imports
- # without triggering spec.__init__
- spec_dir = Path(__file__).parent.parent / "spec"
- if str(spec_dir) not in sys.path:
- sys.path.insert(0, str(spec_dir))
-
- try:
- # Import directly from validate_pkg without going through spec package
- from validate_pkg.spec_validator import SpecValidator
-
- # Cache the imported value in this module
- globals()["SpecValidator"] = SpecValidator
- return SpecValidator
- finally:
- # Clean up path modification
- if str(spec_dir) in sys.path:
- sys.path.remove(str(spec_dir))
-
- raise AttributeError(
- f"module 'validate_spec.spec_validator' has no attribute '{name}'"
- )
diff --git a/auto-claude/workspace.py b/auto-claude/workspace.py
deleted file mode 100644
index fec822f1..00000000
--- a/auto-claude/workspace.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"""
-Backward compatibility shim - import from core.workspace package.
-
-This file exists to maintain backward compatibility for code that imports
-from 'workspace' instead of 'core.workspace'. The workspace module has been
-refactored into a package (core/workspace/) with multiple sub-modules.
-
-IMPLEMENTATION: To avoid triggering core/__init__.py (which imports modules
-with heavy dependencies like claude_agent_sdk), we:
-1. Create a minimal fake 'core' module to satisfy Python's import system
-2. Load core.workspace package directly using importlib
-3. Register it in sys.modules
-4. Re-export everything
-
-This allows 'from workspace import X' to work without requiring all of core's dependencies.
-"""
-
-import importlib.util
-import sys
-from pathlib import Path
-from types import ModuleType
-
-# Ensure auto-claude is in sys.path
-_auto_claude_dir = Path(__file__).parent
-if str(_auto_claude_dir) not in sys.path:
- sys.path.insert(0, str(_auto_claude_dir))
-
-# Create a minimal 'core' module if it doesn't exist (to avoid importing core/__init__.py)
-if "core" not in sys.modules:
- _core_module = ModuleType("core")
- _core_module.__file__ = str(_auto_claude_dir / "core" / "__init__.py")
- _core_module.__path__ = [str(_auto_claude_dir / "core")]
- sys.modules["core"] = _core_module
-
-# Now load core.workspace package directly
-_workspace_init = _auto_claude_dir / "core" / "workspace" / "__init__.py"
-_spec = importlib.util.spec_from_file_location("core.workspace", _workspace_init)
-_workspace_module = importlib.util.module_from_spec(_spec)
-sys.modules["core.workspace"] = _workspace_module
-_spec.loader.exec_module(_workspace_module)
-
-# Re-export everything from core.workspace
-from core.workspace import * # noqa: F401, F403
-
-__all__ = _workspace_module.__all__
diff --git a/guides/CLI-USAGE.md b/guides/CLI-USAGE.md
index 4e9534ef..09ee315f 100644
--- a/guides/CLI-USAGE.md
+++ b/guides/CLI-USAGE.md
@@ -15,10 +15,10 @@ This document covers terminal-only usage of Auto Claude. **For most users, we re
## Setup
-**Step 1:** Navigate to the auto-claude directory
+**Step 1:** Navigate to the backend directory
```bash
-cd auto-claude
+cd apps/backend
```
**Step 2:** Set up Python environment
@@ -39,14 +39,16 @@ cp .env.example .env
# Get your OAuth token
claude setup-token
-# Add the token to .env
+# Add the token to apps/backend/.env
# CLAUDE_CODE_OAUTH_TOKEN=your-token-here
```
## Creating Specs
+All commands below should be run from the `apps/backend/` directory:
+
```bash
-# Activate the virtual environment
+# Activate the virtual environment (if not already active)
source .venv/bin/activate
# Create a spec interactively
@@ -116,6 +118,9 @@ Auto Claude uses Git worktrees for isolated builds:
cd .worktrees/auto-claude/
npm run dev # or your project's run command
+# Return to backend directory to run management commands
+cd apps/backend
+
# See what was changed
python run.py --spec 001 --review
diff --git a/guides/DOCKER-SETUP.md b/guides/DOCKER-SETUP.md
deleted file mode 100644
index 8acd6964..00000000
--- a/guides/DOCKER-SETUP.md
+++ /dev/null
@@ -1,435 +0,0 @@
-# Docker & FalkorDB Setup Guide
-
-This guide covers installing and troubleshooting Docker for Auto Claude's Memory Layer. The Memory Layer uses FalkorDB (a graph database) to provide persistent cross-session memory for AI agents.
-
-> **Good news!** If you're using the Desktop UI, it automatically detects Docker and FalkorDB status and offers one-click setup. This guide is for manual setup or troubleshooting.
-
-## Table of Contents
-
-- [Quick Start](#quick-start)
-- [What is Docker?](#what-is-docker)
-- [Installing Docker Desktop](#installing-docker-desktop)
- - [macOS](#macos)
- - [Windows](#windows)
- - [Linux](#linux)
-- [Starting FalkorDB](#starting-falkordb)
-- [Verifying Your Setup](#verifying-your-setup)
-- [Troubleshooting](#troubleshooting)
-- [Advanced Configuration](#advanced-configuration)
-- [Uninstalling](#uninstalling)
-
----
-
-## Quick Start
-
-If Docker Desktop is already installed and running:
-
-```bash
-# Start FalkorDB
-docker run -d --name auto-claude-falkordb -p 6379:6379 falkordb/falkordb:latest
-
-# Verify it's running
-docker ps | grep falkordb
-```
-
----
-
-## What is Docker?
-
-Docker is a tool that runs applications in isolated "containers". Think of it as a lightweight virtual machine that:
-
-- **Keeps things contained** - FalkorDB runs inside Docker without affecting your system
-- **Makes setup easy** - One command to start, no complex installation
-- **Works everywhere** - Same setup on Mac, Windows, and Linux
-
-**You don't need to understand Docker** - just install Docker Desktop and Auto Claude handles the rest.
-
----
-
-## Installing Docker Desktop
-
-### macOS
-
-#### Step 1: Download
-
-| Mac Type | Download Link |
-|----------|---------------|
-| **Apple Silicon (M1/M2/M3/M4)** | [Download for Apple Chip](https://desktop.docker.com/mac/main/arm64/Docker.dmg) |
-| **Intel** | [Download for Intel Chip](https://desktop.docker.com/mac/main/amd64/Docker.dmg) |
-
-> **Which do I have?** Click the Apple logo () → "About This Mac". Look for "Chip" - if it says Apple M1/M2/M3/M4, use Apple Silicon. If it says Intel, use Intel.
-
-#### Step 2: Install
-
-1. Open the downloaded `.dmg` file
-2. Drag the Docker icon to your Applications folder
-3. Open Docker from Applications (or Spotlight: ⌘+Space, type "Docker")
-4. Click "Open" if you see a security warning
-5. **Wait** - Docker takes 1-2 minutes to start the first time
-
-#### Step 3: Verify
-
-Look for the whale icon (🐳) in your menu bar. When it stops animating, Docker is ready.
-
-Open Terminal and run:
-
-```bash
-docker --version
-# Expected: Docker version 24.x.x or higher
-```
-
-### Windows
-
-#### Prerequisites
-
-- Windows 10 (version 2004 or higher) or Windows 11
-- WSL 2 enabled (Docker will prompt you to install it)
-
-#### Step 1: Download
-
-[Download Docker Desktop for Windows](https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe)
-
-#### Step 2: Install
-
-1. Run the downloaded installer
-2. **Keep "Use WSL 2" checked** (recommended)
-3. Follow the installation wizard with default settings
-4. **Restart your computer** when prompted
-5. After restart, Docker Desktop will start automatically
-
-#### Step 3: WSL 2 Setup (if prompted)
-
-If Docker shows a WSL 2 warning:
-
-1. Open PowerShell as Administrator
-2. Run:
- ```powershell
- wsl --install
- ```
-3. Restart your computer
-4. Open Docker Desktop again
-
-#### Step 4: Verify
-
-Look for the whale icon (🐳) in your system tray. When it stops animating, Docker is ready.
-
-Open PowerShell or Command Prompt and run:
-
-```bash
-docker --version
-# Expected: Docker version 24.x.x or higher
-```
-
-### Linux
-
-#### Ubuntu/Debian
-
-```bash
-# Update package index
-sudo apt-get update
-
-# Install prerequisites
-sudo apt-get install ca-certificates curl gnupg
-
-# Add Docker's official GPG key
-sudo install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-sudo chmod a+r /etc/apt/keyrings/docker.gpg
-
-# Add the repository
-echo \
- "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
- $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
- sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
-
-# Install Docker
-sudo apt-get update
-sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
-
-# Add your user to the docker group (to run without sudo)
-sudo usermod -aG docker $USER
-
-# Log out and back in, then verify
-docker --version
-```
-
-#### Fedora
-
-```bash
-# Install Docker
-sudo dnf -y install dnf-plugins-core
-sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
-sudo dnf install docker-ce docker-ce-cli containerd.io docker-compose-plugin
-
-# Start Docker
-sudo systemctl start docker
-sudo systemctl enable docker
-
-# Add your user to the docker group
-sudo usermod -aG docker $USER
-```
-
----
-
-## Starting FalkorDB
-
-### Option 1: Using Docker Compose (Recommended)
-
-From the Auto Claude root directory:
-
-```bash
-# Start FalkorDB only (for Python library integration)
-docker-compose up -d falkordb
-
-# Or start both FalkorDB + Graphiti MCP server (for agent memory access)
-docker-compose up -d
-```
-
-This uses the project's `docker-compose.yml` which is pre-configured.
-
-### Option 2: Using Docker Run
-
-```bash
-docker run -d \
- --name auto-claude-falkordb \
- -p 6379:6379 \
- --restart unless-stopped \
- falkordb/falkordb:latest
-```
-
-### Option 3: Let the Desktop UI Handle It
-
-If you're using the Auto Claude Desktop UI:
-
-1. Go to Project Settings → Memory Backend
-2. Enable "Use Graphiti"
-3. The UI will show Docker/FalkorDB status
-4. Click "Start" to launch FalkorDB automatically
-
----
-
-## Starting the Graphiti MCP Server (Optional)
-
-The Graphiti MCP server allows Claude agents to directly search and add to the knowledge graph during builds. This is optional but recommended for the best memory experience.
-
-### Prerequisites
-
-1. FalkorDB must be running
-2. OpenAI API key (for embeddings)
-
-### Setup
-
-**For CLI users** - The API key is read from `auto-claude/.env`:
-
-```bash
-docker-compose up -d
-```
-
-**For Frontend/UI users** - Create a `.env` file in the project root:
-
-```bash
-# Copy the example file
-cp .env.example .env
-
-# Edit and add your OpenAI API key
-nano .env # or use any text editor
-
-# Start the services
-docker-compose up -d
-```
-
-### Verify MCP Server is Running
-
-```bash
-# Check container status
-docker ps | grep graphiti-mcp
-
-# Check health endpoint
-curl http://localhost:8000/health
-
-# View logs if there are issues
-docker logs auto-claude-graphiti-mcp
-```
-
-### Configure Auto Claude to Use MCP
-
-In Project Settings → Memory Backend:
-- Enable "Enable Agent Memory Access"
-- Set MCP URL to: `http://localhost:8000/mcp/`
-
----
-
-## Verifying Your Setup
-
-### Check Docker is Running
-
-```bash
-docker info
-# Should show Docker system information without errors
-```
-
-### Check FalkorDB is Running
-
-```bash
-docker ps | grep falkordb
-# Should show the running container
-```
-
-### Test FalkorDB Connection
-
-```bash
-docker exec auto-claude-falkordb redis-cli PING
-# Expected response: PONG
-```
-
-### Check Logs (if something seems wrong)
-
-```bash
-docker logs auto-claude-falkordb
-```
-
----
-
-## Troubleshooting
-
-### Docker Issues
-
-| Problem | Solution |
-|---------|----------|
-| **"docker: command not found"** | Docker Desktop isn't installed or isn't in PATH. Reinstall Docker Desktop. |
-| **"Cannot connect to Docker daemon"** | Docker Desktop isn't running. Open Docker Desktop and wait for it to start. |
-| **"permission denied"** | On Linux, add your user to the docker group: `sudo usermod -aG docker $USER` then log out and back in. |
-| **Docker Desktop won't start** | Try restarting your computer. On Mac, check System Preferences → Security for blocked apps. |
-| **"Docker Desktop requires macOS 12"** | Update macOS in System Preferences → Software Update. |
-| **"WSL 2 installation incomplete"** | Run `wsl --install` in PowerShell (as Admin) and restart. |
-
-### FalkorDB Issues
-
-| Problem | Solution |
-|---------|----------|
-| **Container won't start** | Check if port 6379 is in use: `lsof -i :6379` (Mac/Linux) or `netstat -ano | findstr 6379` (Windows) |
-| **"port is already allocated"** | Stop conflicting container: `docker stop auto-claude-falkordb && docker rm auto-claude-falkordb` |
-| **Connection refused** | Verify container is running: `docker ps`. If not listed, start it again. |
-| **Container crashes immediately** | Check logs: `docker logs auto-claude-falkordb`. May need more memory. |
-
-### Graphiti MCP Server Issues
-
-| Problem | Solution |
-|---------|----------|
-| **"OPENAI_API_KEY must be set"** | Create `.env` file with your API key: `echo "OPENAI_API_KEY=sk-your-key" > .env` |
-| **"DATABASE_TYPE must be set"** | Using old docker run command. Use `docker-compose up -d` instead. |
-| **Container keeps restarting** | Check logs: `docker logs auto-claude-graphiti-mcp`. Usually missing API key. |
-| **Platform warning on Apple Silicon** | This is normal - the image runs via Rosetta emulation. It may be slower but works. |
-| **Health check fails** | Wait 30 seconds for startup. Check: `curl http://localhost:8000/health` |
-
-### Memory/Performance Issues
-
-| Problem | Solution |
-|---------|----------|
-| **Docker using too much memory** | Open Docker Desktop → Settings → Resources → Memory. Reduce to 2-4GB. |
-| **Docker using too much disk** | Run `docker system prune -a` to clean unused images and containers. |
-| **Computer running slow** | Quit Docker Desktop when not using Auto Claude. FalkorDB only needs to run during active sessions. |
-
-### Network Issues
-
-| Problem | Solution |
-|---------|----------|
-| **"network not found"** | Run `docker network create auto-claude-network` or use `docker-compose up` |
-| **Can't connect from app** | Ensure port 6379 is exposed. Check firewall isn't blocking localhost connections. |
-
----
-
-## Advanced Configuration
-
-### Custom Port
-
-If port 6379 is in use, change it:
-
-```bash
-# Using docker run
-docker run -d --name auto-claude-falkordb -p 6381:6379 falkordb/falkordb:latest
-```
-
-Then update Auto Claude settings to use port 6381.
-
-### Persistent Data
-
-To persist FalkorDB data between container restarts:
-
-```bash
-docker run -d \
- --name auto-claude-falkordb \
- -p 6379:6379 \
- -v auto-claude-falkordb-data:/data \
- --restart unless-stopped \
- falkordb/falkordb:latest
-```
-
-### Memory Limits
-
-To limit FalkorDB memory usage:
-
-```bash
-docker run -d \
- --name auto-claude-falkordb \
- -p 6379:6379 \
- --memory=2g \
- --restart unless-stopped \
- falkordb/falkordb:latest
-```
-
-### Running on a Remote Server
-
-If running Docker on a different machine:
-
-1. Expose the port on the server:
- ```bash
- docker run -d -p 0.0.0.0:6379:6379 falkordb/falkordb:latest
- ```
-
-2. Update Auto Claude settings:
- - Set `GRAPHITI_FALKORDB_HOST=your-server-ip`
- - Set `GRAPHITI_FALKORDB_PORT=6379`
-
----
-
-## Uninstalling
-
-### Stop and Remove FalkorDB
-
-```bash
-docker stop auto-claude-falkordb
-docker rm auto-claude-falkordb
-```
-
-### Remove FalkorDB Image
-
-```bash
-docker rmi falkordb/falkordb:latest
-```
-
-### Remove All Docker Data
-
-```bash
-docker system prune -a --volumes
-```
-
-### Uninstall Docker Desktop
-
-- **Mac**: Drag Docker from Applications to Trash, then empty Trash
-- **Windows**: Control Panel → Programs → Uninstall Docker Desktop
-- **Linux**: `sudo apt-get remove docker-ce docker-ce-cli containerd.io`
-
----
-
-## Getting Help
-
-If you're still having issues:
-
-1. Check the [Auto Claude GitHub Issues](https://github.com/auto-claude/auto-claude/issues)
-2. Search for your error message
-3. Create a new issue with:
- - Your operating system and version
- - Docker version (`docker --version`)
- - Error message or logs
- - Steps you've already tried
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..2ea8b276
--- /dev/null
+++ b/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "auto-claude",
+ "version": "2.7.2",
+ "description": "Autonomous multi-agent coding framework powered by Claude AI",
+ "license": "AGPL-3.0",
+ "author": "Auto Claude Team",
+ "scripts": {
+ "install:backend": "node scripts/install-backend.js",
+ "install:frontend": "cd apps/frontend && npm install",
+ "install:all": "npm run install:backend && npm run install:frontend",
+ "start": "cd apps/frontend && npm run build && npm run start",
+ "dev": "cd apps/frontend && npm run dev",
+ "dev:debug": "DEBUG=true cd apps/frontend && npm run dev",
+ "dev:mcp": "cd apps/frontend && npm run dev:mcp",
+ "build": "cd apps/frontend && npm run build",
+ "lint": "cd apps/frontend && npm run lint",
+ "test": "cd apps/frontend && npm test",
+ "test:backend": "node scripts/test-backend.js",
+ "package": "cd apps/frontend && npm run package",
+ "package:mac": "cd apps/frontend && npm run package:mac",
+ "package:win": "cd apps/frontend && npm run package:win",
+ "package:linux": "cd apps/frontend && npm run package:linux"
+ },
+ "engines": {
+ "node": ">=24.0.0",
+ "npm": ">=10.0.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/AndyMik90/Auto-Claude.git"
+ },
+ "keywords": [
+ "ai",
+ "claude",
+ "autonomous",
+ "coding",
+ "agents",
+ "electron"
+ ]
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 00000000..9b60ae17
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,9 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .: {}
diff --git a/scripts/bump-version.js b/scripts/bump-version.js
index c9308aab..22ee2dc3 100644
--- a/scripts/bump-version.js
+++ b/scripts/bump-version.js
@@ -100,20 +100,27 @@ function checkGitStatus() {
// Update package.json version
function updatePackageJson(newVersion) {
- const packagePath = path.join(__dirname, '..', 'auto-claude-ui', 'package.json');
+ const frontendPath = path.join(__dirname, '..', 'apps', 'frontend', 'package.json');
+ const rootPath = path.join(__dirname, '..', 'package.json');
- if (!fs.existsSync(packagePath)) {
- error(`package.json not found at ${packagePath}`);
+ if (!fs.existsSync(frontendPath)) {
+ error(`package.json not found at ${frontendPath}`);
}
- const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
- const oldVersion = packageJson.version;
+ // Update frontend package.json
+ const frontendJson = JSON.parse(fs.readFileSync(frontendPath, 'utf8'));
+ const oldVersion = frontendJson.version;
+ frontendJson.version = newVersion;
+ fs.writeFileSync(frontendPath, JSON.stringify(frontendJson, null, 2) + '\n');
- packageJson.version = newVersion;
+ // Update root package.json if it exists
+ if (fs.existsSync(rootPath)) {
+ const rootJson = JSON.parse(fs.readFileSync(rootPath, 'utf8'));
+ rootJson.version = newVersion;
+ fs.writeFileSync(rootPath, JSON.stringify(rootJson, null, 2) + '\n');
+ }
- fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2) + '\n');
-
- return { oldVersion, packagePath };
+ return { oldVersion, packagePath: frontendPath };
}
// Main function
@@ -133,7 +140,7 @@ function main() {
success('Git working directory is clean');
// 2. Read current version
- const packagePath = path.join(__dirname, '..', 'auto-claude-ui', 'package.json');
+ const packagePath = path.join(__dirname, '..', 'apps', 'frontend', 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
const currentVersion = packageJson.version;
info(`Current version: ${currentVersion}`);
@@ -153,7 +160,7 @@ function main() {
// 5. Create git commit
info('Creating git commit...');
- exec('git add auto-claude-ui/package.json');
+ exec('git add apps/frontend/package.json package.json');
exec(`git commit -m "chore: bump version to ${newVersion}"`);
success(`Created commit: "chore: bump version to ${newVersion}"`);
diff --git a/scripts/install-backend.js b/scripts/install-backend.js
new file mode 100644
index 00000000..d1507a08
--- /dev/null
+++ b/scripts/install-backend.js
@@ -0,0 +1,104 @@
+#!/usr/bin/env node
+/**
+ * Cross-platform backend installer script
+ * Handles Python venv creation and dependency installation on Windows/Mac/Linux
+ */
+
+const { execSync, spawnSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+const os = require('os');
+
+const isWindows = os.platform() === 'win32';
+const backendDir = path.join(__dirname, '..', 'apps', 'backend');
+const venvDir = path.join(backendDir, '.venv');
+
+console.log('Installing Auto Claude backend dependencies...\n');
+
+// Helper to run commands
+function run(cmd, options = {}) {
+ console.log(`> ${cmd}`);
+ try {
+ execSync(cmd, { stdio: 'inherit', cwd: backendDir, ...options });
+ return true;
+ } catch (error) {
+ return false;
+ }
+}
+
+// Find Python 3.12
+function findPython() {
+ const candidates = isWindows
+ ? ['py -3.12', 'python3.12', 'python']
+ : ['python3.12', 'python3', 'python'];
+
+ for (const cmd of candidates) {
+ try {
+ const result = spawnSync(cmd.split(' ')[0], [...cmd.split(' ').slice(1), '--version'], {
+ encoding: 'utf8',
+ shell: true,
+ });
+ if (result.status === 0 && result.stdout.includes('3.12')) {
+ console.log(`Found Python 3.12: ${cmd} -> ${result.stdout.trim()}`);
+ return cmd;
+ }
+ } catch (e) {
+ // Continue to next candidate
+ }
+ }
+ return null;
+}
+
+// Get pip path based on platform
+function getPipPath() {
+ return isWindows
+ ? path.join(venvDir, 'Scripts', 'pip.exe')
+ : path.join(venvDir, 'bin', 'pip');
+}
+
+// Main installation
+async function main() {
+ // Check for Python 3.12
+ const python = findPython();
+ if (!python) {
+ console.error('\nError: Python 3.12 is required but not found.');
+ console.error('Please install Python 3.12:');
+ if (isWindows) {
+ console.error(' winget install Python.Python.3.12');
+ } else if (os.platform() === 'darwin') {
+ console.error(' brew install python@3.12');
+ } else {
+ console.error(' sudo apt install python3.12 python3.12-venv');
+ }
+ process.exit(1);
+ }
+
+ // Remove existing venv if present
+ if (fs.existsSync(venvDir)) {
+ console.log('\nRemoving existing virtual environment...');
+ fs.rmSync(venvDir, { recursive: true, force: true });
+ }
+
+ // Create virtual environment
+ console.log('\nCreating virtual environment...');
+ if (!run(`${python} -m venv .venv`)) {
+ console.error('Failed to create virtual environment');
+ process.exit(1);
+ }
+
+ // Install dependencies
+ console.log('\nInstalling dependencies...');
+ const pip = getPipPath();
+ if (!run(`"${pip}" install -r requirements.txt`)) {
+ console.error('Failed to install dependencies');
+ process.exit(1);
+ }
+
+ console.log('\nBackend installation complete!');
+ console.log(`Virtual environment: ${venvDir}`);
+}
+
+main().catch((err) => {
+ console.error('Installation failed:', err);
+ process.exit(1);
+});
diff --git a/scripts/test-backend.js b/scripts/test-backend.js
new file mode 100644
index 00000000..9a1b9098
--- /dev/null
+++ b/scripts/test-backend.js
@@ -0,0 +1,53 @@
+#!/usr/bin/env node
+/**
+ * Cross-platform backend test runner script
+ * Runs pytest using the correct virtual environment path for Windows/Mac/Linux
+ */
+
+const { execSync } = require('child_process');
+const path = require('path');
+const fs = require('fs');
+const os = require('os');
+
+const isWindows = os.platform() === 'win32';
+const rootDir = path.join(__dirname, '..');
+const backendDir = path.join(rootDir, 'apps', 'backend');
+const testsDir = path.join(rootDir, 'tests');
+const venvDir = path.join(backendDir, '.venv');
+
+// Get pytest path based on platform
+const pytestPath = isWindows
+ ? path.join(venvDir, 'Scripts', 'pytest.exe')
+ : path.join(venvDir, 'bin', 'pytest');
+
+// Check if venv exists
+if (!fs.existsSync(venvDir)) {
+ console.error('Error: Virtual environment not found.');
+ console.error('Run "npm run install:backend" first.');
+ process.exit(1);
+}
+
+// Check if pytest is installed
+if (!fs.existsSync(pytestPath)) {
+ console.error('Error: pytest not found in virtual environment.');
+ console.error('Install test dependencies:');
+ const pipPath = isWindows
+ ? path.join(venvDir, 'Scripts', 'pip.exe')
+ : path.join(venvDir, 'bin', 'pip');
+ console.error(` "${pipPath}" install -r tests/requirements-test.txt`);
+ process.exit(1);
+}
+
+// Get any additional args passed to the script
+const args = process.argv.slice(2);
+const testArgs = args.length > 0 ? args.join(' ') : '-v';
+
+// Run pytest
+const cmd = `"${pytestPath}" "${testsDir}" ${testArgs}`;
+console.log(`> ${cmd}\n`);
+
+try {
+ execSync(cmd, { stdio: 'inherit', cwd: rootDir });
+} catch (error) {
+ process.exit(error.status || 1);
+}
diff --git a/tests/conftest.py b/tests/conftest.py
index 44ff36a4..6a76c075 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -42,8 +42,8 @@ if 'claude_code_sdk' not in sys.modules:
sys.modules['claude_code_sdk'] = _create_sdk_mock()
sys.modules['claude_code_sdk.types'] = MagicMock()
-# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+# Add apps/backend directory to path for imports
+sys.path.insert(0, str(Path(__file__).parent.parent / "apps" / "backend"))
# =============================================================================
diff --git a/tests/qa_report_helpers.py b/tests/qa_report_helpers.py
index 95084522..2f116efe 100644
--- a/tests/qa_report_helpers.py
+++ b/tests/qa_report_helpers.py
@@ -101,7 +101,7 @@ def setup_qa_report_mocks() -> None:
sys.modules['client'] = mock_client
# Add auto-claude path for imports
- sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+ sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
def cleanup_qa_report_mocks() -> None:
diff --git a/tests/review_fixtures.py b/tests/review_fixtures.py
index 5fab6be0..6580cc0a 100644
--- a/tests/review_fixtures.py
+++ b/tests/review_fixtures.py
@@ -12,7 +12,7 @@ from typing import Generator
import pytest
-from review import ReviewState
+from review.state import ReviewState
@pytest.fixture
diff --git a/tests/test_agent_architecture.py b/tests/test_agent_architecture.py
index c03ce7d8..54262880 100644
--- a/tests/test_agent_architecture.py
+++ b/tests/test_agent_architecture.py
@@ -21,8 +21,8 @@ from pathlib import Path
import pytest
-# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+# Add apps/backend directory to path for imports
+sys.path.insert(0, str(Path(__file__).parent.parent / "apps" / "backend"))
class TestNoExternalParallelism:
@@ -30,7 +30,7 @@ class TestNoExternalParallelism:
def test_no_coordinator_module(self):
"""No external coordinator module should exist."""
- coordinator_path = Path(__file__).parent.parent / "auto-claude" / "coordinator.py"
+ coordinator_path = Path(__file__).parent.parent / "apps" / "backend" / "coordinator.py"
assert not coordinator_path.exists(), (
"coordinator.py should not exist. Parallel orchestration is handled "
"internally by the agent using Claude Code's Task tool."
@@ -38,7 +38,7 @@ class TestNoExternalParallelism:
def test_no_task_tool_module(self):
"""No task_tool wrapper module should exist."""
- task_tool_path = Path(__file__).parent.parent / "auto-claude" / "task_tool.py"
+ task_tool_path = Path(__file__).parent.parent / "apps" / "backend" / "task_tool.py"
assert not task_tool_path.exists(), (
"task_tool.py should not exist. The agent spawns subagents directly "
"using Claude Code's built-in Task tool."
@@ -58,7 +58,7 @@ class TestCLIInterface:
def test_no_parallel_flag(self):
"""CLI should not have --parallel argument."""
- run_py_path = Path(__file__).parent.parent / "auto-claude" / "run.py"
+ run_py_path = Path(__file__).parent.parent / "apps" / "backend" / "run.py"
content = run_py_path.read_text()
# Check that --parallel is not defined as an argument
@@ -73,7 +73,7 @@ class TestCLIInterface:
def test_no_parallel_examples_in_docs(self):
"""CLI documentation should not mention parallel mode."""
- run_py_path = Path(__file__).parent.parent / "auto-claude" / "run.py"
+ run_py_path = Path(__file__).parent.parent / "apps" / "backend" / "run.py"
content = run_py_path.read_text()
# The docstring should not have --parallel examples
@@ -125,7 +125,7 @@ class TestAgentPrompt:
def test_mentions_subagents(self):
"""Agent prompt mentions subagent capability."""
- coder_prompt_path = Path(__file__).parent.parent / "auto-claude" / "prompts" / "coder.md"
+ coder_prompt_path = Path(__file__).parent.parent / "apps" / "backend" / "prompts" / "coder.md"
content = coder_prompt_path.read_text()
assert "subagent" in content.lower(), (
@@ -134,7 +134,7 @@ class TestAgentPrompt:
def test_mentions_parallel_capability(self):
"""Agent prompt mentions parallel/concurrent capability."""
- coder_prompt_path = Path(__file__).parent.parent / "auto-claude" / "prompts" / "coder.md"
+ coder_prompt_path = Path(__file__).parent.parent / "apps" / "backend" / "prompts" / "coder.md"
content = coder_prompt_path.read_text()
has_task_tool = "task tool" in content.lower() or "Task tool" in content
@@ -158,7 +158,7 @@ class TestModuleIntegrity:
def test_run_module_valid_syntax(self):
"""Run module has valid Python syntax."""
- run_py_path = Path(__file__).parent.parent / "auto-claude" / "run.py"
+ run_py_path = Path(__file__).parent.parent / "apps" / "backend" / "run.py"
content = run_py_path.read_text()
try:
@@ -169,7 +169,7 @@ class TestModuleIntegrity:
def test_no_coordinator_imports(self):
"""Core modules don't import coordinator."""
for filename in ["run.py", "core/agent.py"]:
- filepath = Path(__file__).parent.parent / "auto-claude" / filename
+ filepath = Path(__file__).parent.parent / "apps" / "backend" / filename
content = filepath.read_text()
assert "from coordinator import" not in content, (
@@ -182,7 +182,7 @@ class TestModuleIntegrity:
def test_no_task_tool_imports(self):
"""Core modules don't import task_tool."""
for filename in ["run.py", "core/agent.py"]:
- filepath = Path(__file__).parent.parent / "auto-claude" / filename
+ filepath = Path(__file__).parent.parent / "apps" / "backend" / filename
content = filepath.read_text()
assert "from task_tool import" not in content, (
@@ -199,7 +199,7 @@ class TestProjectDocumentation:
def test_no_parallel_cli_documented(self):
"""CLAUDE.md doesn't document --parallel flag."""
claude_md_path = Path(__file__).parent.parent / "CLAUDE.md"
- content = claude_md_path.read_text()
+ content = claude_md_path.read_text(encoding="utf-8")
assert "--parallel 2" not in content, (
"CLAUDE.md should not document --parallel flag"
@@ -208,7 +208,7 @@ class TestProjectDocumentation:
def test_subagent_architecture_documented(self):
"""CLAUDE.md documents subagent-based architecture."""
claude_md_path = Path(__file__).parent.parent / "CLAUDE.md"
- content = claude_md_path.read_text()
+ content = claude_md_path.read_text(encoding="utf-8")
has_subagent = "subagent" in content.lower()
has_task_tool = "task tool" in content.lower()
@@ -305,7 +305,7 @@ class TestSubtaskTerminology:
def test_implementation_plan_uses_subtask_class(self):
"""Implementation plan uses Subtask class."""
- impl_plan_path = Path(__file__).parent.parent / "auto-claude" / "implementation_plan" / "main.py"
+ impl_plan_path = Path(__file__).parent.parent / "apps" / "backend" / "implementation_plan" / "main.py"
content = impl_plan_path.read_text()
# Check that it re-exports or imports Subtask and SubtaskStatus
@@ -318,7 +318,7 @@ class TestSubtaskTerminology:
def test_progress_uses_subtask_terminology(self):
"""Progress module uses subtask terminology."""
- progress_path = Path(__file__).parent.parent / "auto-claude" / "core" / "progress.py"
+ progress_path = Path(__file__).parent.parent / "apps" / "backend" / "core" / "progress.py"
content = progress_path.read_text()
assert "subtask" in content.lower(), (
diff --git a/tests/test_analyzer_port_detection.py b/tests/test_analyzer_port_detection.py
index 3451f208..eada6586 100644
--- a/tests/test_analyzer_port_detection.py
+++ b/tests/test_analyzer_port_detection.py
@@ -17,7 +17,7 @@ import sys
import json
# Add parent directory to path to import analyzer
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from analyzer import ServiceAnalyzer
diff --git a/tests/test_ci_discovery.py b/tests/test_ci_discovery.py
index 8f2c2e8d..a55d6b91 100644
--- a/tests/test_ci_discovery.py
+++ b/tests/test_ci_discovery.py
@@ -18,7 +18,7 @@ import pytest
# Add auto-claude to path for imports
import sys
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from ci_discovery import (
CIConfig,
diff --git a/tests/test_critique_integration.py b/tests/test_critique_integration.py
index 1dfb776c..ad80e95e 100644
--- a/tests/test_critique_integration.py
+++ b/tests/test_critique_integration.py
@@ -13,7 +13,7 @@ import sys
from pathlib import Path
# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from critique import (
generate_critique_prompt,
diff --git a/tests/test_discovery.py b/tests/test_discovery.py
index 5eb20d46..c83f4626 100644
--- a/tests/test_discovery.py
+++ b/tests/test_discovery.py
@@ -18,7 +18,7 @@ import pytest
# Add auto-claude to path for imports
import sys
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from test_discovery import (
TestFramework,
diff --git a/tests/test_graphiti.py b/tests/test_graphiti.py
index a5fb775f..6243e833 100644
--- a/tests/test_graphiti.py
+++ b/tests/test_graphiti.py
@@ -6,7 +6,7 @@ from unittest.mock import patch, MagicMock
# Add auto-claude to path
import sys
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from graphiti_config import is_graphiti_enabled, get_graphiti_status, GraphitiConfig
diff --git a/tests/test_merge_auto_merger.py b/tests/test_merge_auto_merger.py
index a3b57163..af5d1a1b 100644
--- a/tests/test_merge_auto_merger.py
+++ b/tests/test_merge_auto_merger.py
@@ -23,7 +23,7 @@ from pathlib import Path
import pytest
# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from merge import (
ChangeType,
diff --git a/tests/test_merge_conflict_detector.py b/tests/test_merge_conflict_detector.py
index 11ee0c39..47eb845d 100644
--- a/tests/test_merge_conflict_detector.py
+++ b/tests/test_merge_conflict_detector.py
@@ -20,7 +20,7 @@ from pathlib import Path
import pytest
# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from merge import (
ChangeType,
diff --git a/tests/test_merge_file_tracker.py b/tests/test_merge_file_tracker.py
index 656fa1a1..4a6839da 100644
--- a/tests/test_merge_file_tracker.py
+++ b/tests/test_merge_file_tracker.py
@@ -21,7 +21,7 @@ from pathlib import Path
import pytest
# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
# Add tests directory to path for test_fixtures
sys.path.insert(0, str(Path(__file__).parent))
diff --git a/tests/test_merge_fixtures.py b/tests/test_merge_fixtures.py
index f1edb38e..c201d66d 100644
--- a/tests/test_merge_fixtures.py
+++ b/tests/test_merge_fixtures.py
@@ -19,7 +19,7 @@ from unittest.mock import MagicMock
import pytest
# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from merge import (
SemanticAnalyzer,
diff --git a/tests/test_merge_orchestrator.py b/tests/test_merge_orchestrator.py
index b6aca437..ecaa65c8 100644
--- a/tests/test_merge_orchestrator.py
+++ b/tests/test_merge_orchestrator.py
@@ -23,7 +23,7 @@ from pathlib import Path
import pytest
# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
# Add tests directory to path for test_fixtures
sys.path.insert(0, str(Path(__file__).parent))
diff --git a/tests/test_merge_parallel.py b/tests/test_merge_parallel.py
index be2f9159..fe409f8a 100644
--- a/tests/test_merge_parallel.py
+++ b/tests/test_merge_parallel.py
@@ -18,7 +18,7 @@ from pathlib import Path
import pytest
# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from workspace import ParallelMergeTask, ParallelMergeResult
from core.workspace import _run_parallel_merges
diff --git a/tests/test_merge_semantic_analyzer.py b/tests/test_merge_semantic_analyzer.py
index 6afc049b..e3c58d65 100644
--- a/tests/test_merge_semantic_analyzer.py
+++ b/tests/test_merge_semantic_analyzer.py
@@ -19,7 +19,7 @@ from pathlib import Path
import pytest
# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
# Add tests directory to path for test_fixtures
sys.path.insert(0, str(Path(__file__).parent))
diff --git a/tests/test_merge_types.py b/tests/test_merge_types.py
index a2a420ed..68e0a157 100644
--- a/tests/test_merge_types.py
+++ b/tests/test_merge_types.py
@@ -21,7 +21,7 @@ from pathlib import Path
import pytest
# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from merge import (
ChangeType,
diff --git a/tests/test_qa_criteria.py b/tests/test_qa_criteria.py
index 47bf947f..00e963f0 100644
--- a/tests/test_qa_criteria.py
+++ b/tests/test_qa_criteria.py
@@ -100,7 +100,7 @@ mock_client.create_client = MagicMock()
sys.modules['client'] = mock_client
# Now we can safely add the auto-claude path and import
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
# Import criteria functions directly to avoid going through qa/__init__.py
# which imports reviewer and fixer that need the SDK
diff --git a/tests/test_qa_loop_enhancements.py b/tests/test_qa_loop_enhancements.py
index f758f627..4fcbf309 100644
--- a/tests/test_qa_loop_enhancements.py
+++ b/tests/test_qa_loop_enhancements.py
@@ -18,7 +18,7 @@ import pytest
# Add auto-claude to path for imports
import sys
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from qa_loop import (
# Iteration tracking
diff --git a/tests/test_risk_classifier.py b/tests/test_risk_classifier.py
index 5c45a1c8..2f12fccd 100644
--- a/tests/test_risk_classifier.py
+++ b/tests/test_risk_classifier.py
@@ -17,7 +17,7 @@ from pathlib import Path
import sys
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from risk_classifier import (
RiskClassifier,
diff --git a/tests/test_security_scanner.py b/tests/test_security_scanner.py
index d829dcd1..0f1e95be 100644
--- a/tests/test_security_scanner.py
+++ b/tests/test_security_scanner.py
@@ -19,7 +19,7 @@ import pytest
# Add auto-claude to path for imports
import sys
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from security_scanner import (
SecurityVulnerability,
diff --git a/tests/test_service_orchestrator.py b/tests/test_service_orchestrator.py
index 54375786..5a59efd9 100644
--- a/tests/test_service_orchestrator.py
+++ b/tests/test_service_orchestrator.py
@@ -17,7 +17,7 @@ import pytest
# Add auto-claude to path for imports
import sys
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from service_orchestrator import (
ServiceConfig,
diff --git a/tests/test_spec_complexity.py b/tests/test_spec_complexity.py
index 71ec43cf..48b09220 100644
--- a/tests/test_spec_complexity.py
+++ b/tests/test_spec_complexity.py
@@ -50,7 +50,7 @@ sys.modules['claude_agent_sdk'] = mock_agent_sdk
sys.modules['claude_agent_sdk.types'] = mock_agent_types
# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from spec.complexity import (
Complexity,
diff --git a/tests/test_spec_pipeline.py b/tests/test_spec_pipeline.py
index 4d4e7ec1..a6778cd9 100644
--- a/tests/test_spec_pipeline.py
+++ b/tests/test_spec_pipeline.py
@@ -19,7 +19,7 @@ from pathlib import Path
from unittest.mock import MagicMock, patch, AsyncMock
# Add auto-claude directory to path for imports
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
# Store original modules for cleanup
_original_modules = {}
diff --git a/tests/test_thinking_level_validation.py b/tests/test_thinking_level_validation.py
index 09e6b066..186fd193 100644
--- a/tests/test_thinking_level_validation.py
+++ b/tests/test_thinking_level_validation.py
@@ -12,7 +12,7 @@ from pathlib import Path
import pytest
# Add auto-claude to path
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from phase_config import THINKING_BUDGET_MAP, get_thinking_budget
diff --git a/tests/test_validation_strategy.py b/tests/test_validation_strategy.py
index c392f2b7..db916091 100644
--- a/tests/test_validation_strategy.py
+++ b/tests/test_validation_strategy.py
@@ -18,7 +18,7 @@ import pytest
# Add auto-claude to path for imports
import sys
-sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude"))
+sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend"))
from validation_strategy import (
ValidationStep,