Simplify to core git hooks and cascading rules
- Reset to pre-automation version (commit 536d885)
- Add flock locking to pre-commit hook for git corruption prevention
- Update README to reflect simplified scope
- Update CLAUDE.md with focused documentation
- Link to orchestrated-discussions for advanced features
This version focuses on:
- Git pre-commit hooks with safety checks
- Cascading .ai-rules.yml system
- Ramble GUI for feature requests
- Installer bundle generation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
536d885b6b
commit
e37b1a9722
291
CLAUDE.md
291
CLAUDE.md
|
|
@ -4,15 +4,20 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
**CascadingDev (CDev)** is a Git-native AI-human collaboration framework that automates documentation, discussion summaries, and code review directly within repositories. It's a tooling project that generates installer bundles which users run to scaffold new projects with the CDev workflow.
|
**CascadingDev (CDev) - Simplified** is the core of a Git-native AI-human collaboration framework. This simplified version focuses on:
|
||||||
|
|
||||||
|
- Git pre-commit hooks with safety checks
|
||||||
|
- Cascading `.ai-rules.yml` system
|
||||||
|
- Ramble GUI for structured feature requests
|
||||||
|
- Installer bundle generation
|
||||||
|
|
||||||
|
For advanced discussion orchestration, see [Orchestrated Discussions](https://gitea.brrd.tech/rob/orchestrated-discussions).
|
||||||
|
|
||||||
### Key Concept: Two Repositories
|
### Key Concept: Two Repositories
|
||||||
|
|
||||||
- **CascadingDev repo** (this codebase): The tooling that builds installer bundles
|
- **CascadingDev repo** (this codebase): The tooling that builds installer bundles
|
||||||
- **User's project repo**: A new repository scaffolded by running the installer bundle
|
- **User's project repo**: A new repository scaffolded by running the installer bundle
|
||||||
|
|
||||||
This CLAUDE.md describes working on the CascadingDev tooling itself.
|
|
||||||
|
|
||||||
## Repository Architecture
|
## Repository Architecture
|
||||||
|
|
||||||
### Directory Structure
|
### Directory Structure
|
||||||
|
|
@ -33,28 +38,13 @@ CascadingDev/
|
||||||
│ └── create_feature.py # CLI for feature creation
|
│ └── create_feature.py # CLI for feature creation
|
||||||
├── tools/ # Build and test scripts
|
├── tools/ # Build and test scripts
|
||||||
│ ├── build_installer.py # Creates install/ bundle
|
│ ├── build_installer.py # Creates install/ bundle
|
||||||
│ ├── bundle_smoke.py # End-to-end installer test
|
|
||||||
│ └── smoke_test.py # Basic validation
|
│ └── smoke_test.py # Basic validation
|
||||||
├── install/ # Build output (git-ignored)
|
├── install/ # Build output (git-ignored)
|
||||||
│ └── cascadingdev-<ver>/ # Distributable installer bundle
|
└── VERSION # Semantic version
|
||||||
├── docs/ # System design documentation
|
|
||||||
│ ├── DESIGN.md # Comprehensive architecture doc
|
|
||||||
│ └── INSTALL.md # Installation instructions
|
|
||||||
└── VERSION # Semantic version (e.g., 0.1.0)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Core Workflow
|
|
||||||
|
|
||||||
1. **Development**: Modify code in `src/cascadingdev/` or assets in `assets/`
|
|
||||||
2. **Build**: Run `cdev build` to create installer bundle in `install/cascadingdev-<ver>/`
|
|
||||||
3. **Test**: Run `cdev smoke` or `cdev bundle-smoke` to validate
|
|
||||||
4. **Package**: Run `cdev pack` to create distributable ZIP
|
|
||||||
5. **Release**: Run `cdev release --kind [major|minor|patch]` to bump version and rebuild
|
|
||||||
|
|
||||||
## Common Commands
|
## Common Commands
|
||||||
|
|
||||||
### Development Workflow
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Initial setup
|
# Initial setup
|
||||||
python3 -m venv .venv
|
python3 -m venv .venv
|
||||||
|
|
@ -64,84 +54,13 @@ pip install --upgrade pip wheel PySide6
|
||||||
# Install in development mode
|
# Install in development mode
|
||||||
pip install -e .
|
pip install -e .
|
||||||
|
|
||||||
# Check environment and required files
|
# Build the installer bundle
|
||||||
cdev doctor
|
|
||||||
|
|
||||||
# Build the installer bundle (without version bump)
|
|
||||||
cdev build
|
cdev build
|
||||||
|
|
||||||
# Run basic validation
|
# Test-install into a temporary folder
|
||||||
cdev smoke
|
|
||||||
|
|
||||||
# Bump version and rebuild (default: patch)
|
|
||||||
cdev release --kind [major|minor|patch]
|
|
||||||
|
|
||||||
# Create distributable ZIP
|
|
||||||
cdev pack
|
|
||||||
|
|
||||||
# Test the bundle end-to-end
|
|
||||||
cdev bundle-smoke --keep --target /tmp/test-project
|
|
||||||
```
|
|
||||||
|
|
||||||
### Testing the Installer
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Build and test-install into a temporary folder
|
|
||||||
cdev build
|
|
||||||
python install/cascadingdev-*/setup_cascadingdev.py --target /tmp/myproject --no-ramble
|
python install/cascadingdev-*/setup_cascadingdev.py --target /tmp/myproject --no-ramble
|
||||||
|
|
||||||
# Or use bundle-smoke for automated testing
|
|
||||||
cdev bundle-smoke --target /tmp/test --keep
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Working with Git
|
|
||||||
|
|
||||||
The current branch is `converge-cli`. This repository doesn't have a configured main branch, so when creating PRs, verify the target branch with the maintainer.
|
|
||||||
|
|
||||||
## Build System
|
|
||||||
|
|
||||||
### How the Build Works
|
|
||||||
|
|
||||||
The build process (`tools/build_installer.py`) creates a standalone installer bundle:
|
|
||||||
|
|
||||||
1. Reads version from `VERSION` file
|
|
||||||
2. Creates `install/cascadingdev-<version>/` directory
|
|
||||||
3. Copies essential files from `assets/` to bundle:
|
|
||||||
- Templates (*.md, policies.yml, .ai-rules.yml)
|
|
||||||
- Git hooks (pre-commit)
|
|
||||||
- Runtime scripts (ramble.py, create_feature.py)
|
|
||||||
4. Copies `src/cascadingdev/setup_project.py` as the installer entry point
|
|
||||||
5. Creates bundle-local `INSTALL.md` and `VERSION`
|
|
||||||
|
|
||||||
**Important**: All user-facing files must live in `assets/`. The build script is the single point that defines what gets shipped.
|
|
||||||
|
|
||||||
### Bundle Contents
|
|
||||||
|
|
||||||
The installer bundle is self-contained and requires only Python 3.10+ stdlib (PySide6 optional for GUI):
|
|
||||||
|
|
||||||
- `setup_cascadingdev.py` - Main installer script
|
|
||||||
- `ramble.py` - Optional GUI for creating first feature
|
|
||||||
- `create_feature.py` - CLI tool for creating features (also copied to user projects)
|
|
||||||
- `assets/` - All templates, hooks, and configuration files
|
|
||||||
- `VERSION` - Version metadata
|
|
||||||
- `INSTALL.md` - Bundle-local instructions
|
|
||||||
|
|
||||||
### What Gets Shipped vs. What Stays
|
|
||||||
|
|
||||||
**Shipped to user projects:**
|
|
||||||
- `USER_GUIDE.md` - Daily usage instructions
|
|
||||||
- `.ai-rules.yml` - Cascading rules system configuration
|
|
||||||
- `pre-commit` hook - Discussion/summary automation
|
|
||||||
- Feature templates (feature_request.md, discussion templates)
|
|
||||||
- `policies.yml` - Process configuration
|
|
||||||
- `create_feature.py` - Feature creation tool
|
|
||||||
|
|
||||||
**Stays in CascadingDev repo:**
|
|
||||||
- `DESIGN.md` - System architecture (27k+ tokens)
|
|
||||||
- `README.md` - Project overview
|
|
||||||
- Development tools and tests
|
|
||||||
- Source code in `src/`
|
|
||||||
|
|
||||||
## Key Concepts
|
## Key Concepts
|
||||||
|
|
||||||
### Cascading Rules System
|
### Cascading Rules System
|
||||||
|
|
@ -154,183 +73,29 @@ Rules are hierarchical: nearest file takes precedence.
|
||||||
|
|
||||||
### Pre-commit Hook
|
### Pre-commit Hook
|
||||||
|
|
||||||
The bash pre-commit hook (`assets/hooks/pre-commit`) is the core automation engine:
|
The bash pre-commit hook (`assets/hooks/pre-commit`) provides:
|
||||||
- Scans for potential secrets (blocks commit on match)
|
- Scans for potential secrets (blocks commit on match)
|
||||||
- Ensures discussion files have companion `.sum.md` summary files
|
- Ensures discussion files have companion `.sum.md` summary files
|
||||||
- Creates summary templates with marker blocks for AI-maintained content
|
- Uses flock to prevent git corruption from concurrent commits
|
||||||
- Fast and lightweight (pure bash, no Python dependencies)
|
- Fast and lightweight (pure bash, no Python dependencies)
|
||||||
|
|
||||||
### Stage-Per-Discussion Model
|
Environment variables:
|
||||||
|
- `CDEV_SKIP_HOOK=1` - Skip all hook checks
|
||||||
|
- `CDEV_SKIP_SUMMARIES=1` - Skip summary file generation
|
||||||
|
|
||||||
User projects organize features into stages with separate discussion files:
|
### Build System
|
||||||
- `feature.discussion.md` - Initial feature discussion
|
|
||||||
- `design.discussion.md` - Design discussion
|
|
||||||
- `implementation.discussion.md` - Implementation tracking
|
|
||||||
- `testing.discussion.md` - Test planning
|
|
||||||
- `review.discussion.md` - Final review
|
|
||||||
|
|
||||||
Each has a `.sum.md` companion maintained by the hook.
|
The build process (`tools/build_installer.py`) creates a standalone installer bundle:
|
||||||
|
1. Reads version from `VERSION` file
|
||||||
|
2. Creates `install/cascadingdev-<version>/` directory
|
||||||
|
3. Copies essential files from `assets/` to bundle
|
||||||
|
4. Copies `src/cascadingdev/setup_project.py` as the installer entry point
|
||||||
|
|
||||||
### Installation Flow
|
## Related Projects
|
||||||
|
|
||||||
When a user runs `setup_cascadingdev.py`:
|
This project is part of a stack:
|
||||||
1. Prompts for target directory (or uses `--target`)
|
|
||||||
2. Creates canonical folder structure (Docs/features/, process/, etc.)
|
|
||||||
3. Copies templates and hooks from bundle
|
|
||||||
4. Initializes git repository
|
|
||||||
5. Installs pre-commit hook
|
|
||||||
6. Optionally launches Ramble GUI for first feature request
|
|
||||||
7. Creates initial commit to activate the hook
|
|
||||||
|
|
||||||
## Python Module Structure
|
1. **[SmartTools](https://gitea.brrd.tech/rob/SmartTools)** - AI provider abstraction
|
||||||
|
2. **[Orchestrated Discussions](https://gitea.brrd.tech/rob/orchestrated-discussions)** - Multi-agent discussion orchestration
|
||||||
### `src/cascadingdev/cli.py`
|
3. **[Ramble](https://gitea.brrd.tech/rob/ramble)** - AI-powered structured field extraction GUI
|
||||||
|
4. **[Artifact Editor](https://gitea.brrd.tech/rob/artifact-editor)** - AI-enhanced diagram and model creation
|
||||||
Main CLI entry point registered as `cdev` command in pyproject.toml.
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
- `doctor` - Validate environment and required files
|
|
||||||
- `smoke` - Run basic smoke tests
|
|
||||||
- `build` - Build installer bundle
|
|
||||||
- `release` - Bump version and rebuild
|
|
||||||
- `pack` - Create distributable ZIP
|
|
||||||
- `bundle-smoke` - End-to-end installer validation
|
|
||||||
|
|
||||||
### `src/cascadingdev/setup_project.py`
|
|
||||||
|
|
||||||
Standalone installer script (copied to bundle as `setup_cascadingdev.py`). Must work with stdlib only.
|
|
||||||
|
|
||||||
Key functions:
|
|
||||||
- `ensure_dir()`, `write_if_missing()`, `copy_if_missing()` - File operations
|
|
||||||
- `load_template_with_meta()` - Parse templates with JSON metadata
|
|
||||||
- `render_placeholders()` - Simple {Token} replacement
|
|
||||||
- `meta_ramble_config()` - Extract Ramble GUI configuration from template metadata
|
|
||||||
|
|
||||||
### `src/cascadingdev/utils.py`
|
|
||||||
|
|
||||||
Shared utilities for version management and subprocess execution.
|
|
||||||
|
|
||||||
## Design Philosophy
|
|
||||||
|
|
||||||
### Git-Native
|
|
||||||
|
|
||||||
Everything lives in Git as Markdown. No external databases, dashboards, or SaaS dependencies.
|
|
||||||
|
|
||||||
### Self-Documenting
|
|
||||||
|
|
||||||
The first feature request in a user's project defines the entire project. Subsequent features extend that foundation.
|
|
||||||
|
|
||||||
### Deterministic & Reproducible
|
|
||||||
|
|
||||||
The installer bundle is unzip-and-run. No network dependencies during installation (except optional PySide6).
|
|
||||||
|
|
||||||
### Lightweight & Fast
|
|
||||||
|
|
||||||
Pre-commit hook is pure bash for speed. Python orchestration is optional and non-blocking.
|
|
||||||
|
|
||||||
## Important Notes
|
|
||||||
|
|
||||||
### When Modifying Templates
|
|
||||||
|
|
||||||
After changing any file in `assets/`, you must rebuild:
|
|
||||||
```bash
|
|
||||||
cdev build
|
|
||||||
```
|
|
||||||
|
|
||||||
The build script copies from `assets/` to `install/`. Changes don't take effect until rebuilt.
|
|
||||||
|
|
||||||
### When Adding New Templates
|
|
||||||
|
|
||||||
1. Add template to `assets/templates/`
|
|
||||||
2. Update `tools/build_installer.py` to copy it
|
|
||||||
3. Update `src/cascadingdev/setup_project.py` if installer needs to process it
|
|
||||||
4. Rebuild and test with `cdev build && cdev bundle-smoke`
|
|
||||||
|
|
||||||
### Secret Detection
|
|
||||||
|
|
||||||
The pre-commit hook includes basic secret scanning using regex patterns. It blocks commits containing:
|
|
||||||
- API keys (`api_key`, `api-key`)
|
|
||||||
- Secrets (`secret`)
|
|
||||||
- Access tokens (`access_token`, `access-token`)
|
|
||||||
- Private keys (`private_key`, `private-key`)
|
|
||||||
|
|
||||||
Followed by 12+ alphanumeric characters. Use `--no-verify` for false positives, but add proper allowlisting.
|
|
||||||
|
|
||||||
### Python Version Requirement
|
|
||||||
|
|
||||||
Minimum Python 3.10 required. The installer uses modern type hints and f-strings.
|
|
||||||
|
|
||||||
## Architecture Patterns
|
|
||||||
|
|
||||||
### Assets as Single Source of Truth
|
|
||||||
|
|
||||||
All shipped files originate in `assets/`. The build process is the only consumer. This ensures:
|
|
||||||
- No duplicate maintenance
|
|
||||||
- Clear separation of dev vs. shipped files
|
|
||||||
- Easy auditing of what gets distributed
|
|
||||||
|
|
||||||
### Bundle Installer Pattern
|
|
||||||
|
|
||||||
The installer is self-contained and portable:
|
|
||||||
- Single entry point (`setup_cascadingdev.py`)
|
|
||||||
- Stdlib-only dependencies (except optional GUI)
|
|
||||||
- Embeds all necessary assets
|
|
||||||
- Can be zipped and distributed
|
|
||||||
|
|
||||||
### Template Metadata System
|
|
||||||
|
|
||||||
Templates can include JSON metadata in HTML comments:
|
|
||||||
```markdown
|
|
||||||
<!--META {"fields": ["title", "author"], "validators": {"title": "required"}} -->
|
|
||||||
```
|
|
||||||
|
|
||||||
The installer extracts metadata to configure Ramble GUI forms without hardcoding.
|
|
||||||
|
|
||||||
## Common Development Patterns
|
|
||||||
|
|
||||||
### Adding a New CLI Command
|
|
||||||
|
|
||||||
1. Edit `src/cascadingdev/cli.py`
|
|
||||||
2. Add subparser with `sub.add_parser("command_name", help="...")`
|
|
||||||
3. Handle in main() with `if args.cmd == "command_name":`
|
|
||||||
4. Create corresponding tool script in `tools/` if needed
|
|
||||||
|
|
||||||
### Modifying the Pre-commit Hook
|
|
||||||
|
|
||||||
1. Edit `assets/hooks/pre-commit` (bash script)
|
|
||||||
2. Test locally by copying to a test repo's `.git/hooks/`
|
|
||||||
3. Rebuild bundle with `cdev build`
|
|
||||||
4. Test with `cdev bundle-smoke`
|
|
||||||
|
|
||||||
### Testing Changes
|
|
||||||
|
|
||||||
Always test in a fresh project:
|
|
||||||
```bash
|
|
||||||
cdev build
|
|
||||||
cdev bundle-smoke --target /tmp/test-$(date +%s) --keep
|
|
||||||
cd /tmp/test-*
|
|
||||||
# Verify the installation worked correctly
|
|
||||||
```
|
|
||||||
|
|
||||||
## Maintenance Notes
|
|
||||||
|
|
||||||
### Version Management
|
|
||||||
|
|
||||||
Version is stored in `VERSION` file at repo root. Use `cdev release` to bump:
|
|
||||||
- `--kind major` - Breaking changes (0.1.0 → 1.0.0)
|
|
||||||
- `--kind minor` - New features (0.1.0 → 0.2.0)
|
|
||||||
- `--kind patch` - Bug fixes (0.1.0 → 0.1.1)
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
|
|
||||||
- `DESIGN.md` - Comprehensive system design (very large, 27k+ tokens)
|
|
||||||
- `README.md` - Public-facing overview
|
|
||||||
- `USER_GUIDE.md` - Shipped to user projects, daily usage instructions
|
|
||||||
- `CLAUDE.md` - This file, for AI assistant context
|
|
||||||
|
|
||||||
### When DESIGN.md Is Too Large
|
|
||||||
|
|
||||||
The design document is extensive. For specific questions:
|
|
||||||
- Read specific sections with offset/limit parameters
|
|
||||||
- Focus on repository structure and workflow sections
|
|
||||||
- Refer to code comments in `setup_project.py` for installation details
|
|
||||||
|
|
|
||||||
72
README.md
72
README.md
|
|
@ -1,21 +1,26 @@
|
||||||
# CascadingDev (CDev)
|
# CascadingDev (CDev) - Simplified
|
||||||
|
|
||||||
**CDev** — short for *Cascading Development* — is a **Git-native AI–human collaboration framework** that automates documentation, discussion summaries, and code review directly within your repository.
|
**CDev** — short for *Cascading Development* — is a **Git-native AI–human collaboration framework** that uses git hooks and cascading rules to enhance your development workflow.
|
||||||
It lets you build self-documenting projects where AI assists in generating and maintaining feature discussions, design docs, and implementation plans — all version-controlled alongside your code.
|
|
||||||
|
This is the **simplified version** focused on core functionality:
|
||||||
|
- Git pre-commit hooks with safety checks
|
||||||
|
- Cascading `.ai-rules.yml` system
|
||||||
|
- Ramble GUI for capturing structured feature requests
|
||||||
|
|
||||||
|
For advanced discussion orchestration features, see [Orchestrated Discussions](https://gitea.brrd.tech/rob/orchestrated-discussions).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ✨ Key Features
|
## Key Features
|
||||||
- **Git-Integrated Workflow** — every discussion, decision, and artifact lives in Git.
|
|
||||||
- **Cascading Rules System** — nearest `.ai-rules.yml` defines how automation behaves.
|
- **Cascading Rules System** — nearest `.ai-rules.yml` defines behavior at each directory level
|
||||||
- **Stage-Per-Discussion Model** — separate files for feature, design, implementation, testing, and review.
|
- **Pre-commit Hook** — secret scanning, discussion summary creation, git corruption prevention
|
||||||
- **Pre-commit Hook** — automatically maintains summaries, diagrams, and vote tallies.
|
- **Ramble GUI** — PySide6/PyQt5 dialog for capturing structured feature requests
|
||||||
- **Ramble GUI** — friendly PySide6/PyQt5 dialog for capturing structured feature requests.
|
- **Deterministic Builds** — reproducible installer bundle
|
||||||
- **Deterministic Builds** — a reproducible installer bundle you can unzip and run anywhere.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚀 Quick Start (Developers)
|
## Quick Start
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. Create and activate a virtual environment
|
# 1. Create and activate a virtual environment
|
||||||
|
|
@ -26,5 +31,46 @@ pip install --upgrade pip wheel PySide6
|
||||||
# 2. Build the installer bundle
|
# 2. Build the installer bundle
|
||||||
python tools/build_installer.py
|
python tools/build_installer.py
|
||||||
|
|
||||||
# 3. Test-install into a temporary folder
|
# 3. Install into a project folder
|
||||||
python install/cascadingdev-*/setup_cascadingdev.py --target /tmp/myproject --no-ramble
|
python install/cascadingdev-*/setup_cascadingdev.py --target /path/to/myproject
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
CascadingDev/
|
||||||
|
├── assets/
|
||||||
|
│ ├── hooks/pre-commit # Git pre-commit hook
|
||||||
|
│ ├── runtime/ # Runtime scripts (ramble.py, create_feature.py)
|
||||||
|
│ └── templates/ # Discussion and rule templates
|
||||||
|
├── src/cascadingdev/ # Python package
|
||||||
|
│ ├── setup_project.py # Project initialization
|
||||||
|
│ ├── cli.py # Command-line interface
|
||||||
|
│ └── ...
|
||||||
|
├── tools/ # Build and test tools
|
||||||
|
└── docs/ # Documentation
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pre-commit Hook Features
|
||||||
|
|
||||||
|
The pre-commit hook provides:
|
||||||
|
|
||||||
|
1. **Secret Scanning** - Prevents accidental commit of API keys and secrets
|
||||||
|
2. **Summary Files** - Auto-creates `.sum.md` companion files for discussions
|
||||||
|
3. **Concurrency Safety** - Uses flock to prevent git corruption from parallel commits
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
- `CDEV_SKIP_HOOK=1` - Skip all hook checks
|
||||||
|
- `CDEV_SKIP_SUMMARIES=1` - Skip summary file generation
|
||||||
|
|
||||||
|
## Related Projects
|
||||||
|
|
||||||
|
This project is part of a three-layer stack:
|
||||||
|
|
||||||
|
1. **[SmartTools](https://gitea.brrd.tech/rob/SmartTools)** - AI provider abstraction and tool execution
|
||||||
|
2. **[Orchestrated Discussions](https://gitea.brrd.tech/rob/orchestrated-discussions)** - Multi-agent discussion orchestration
|
||||||
|
3. **[Ramble](https://gitea.brrd.tech/rob/ramble)** - AI-powered structured field extraction GUI
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,59 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Safety settings: exit on errors, treat unset variables as errors, and catch pipeline failures
|
#
|
||||||
|
# CascadingDev Pre-commit Hook
|
||||||
|
# =============================
|
||||||
|
# This hook provides safety checks during git commits.
|
||||||
|
#
|
||||||
|
# What it does:
|
||||||
|
# 1. Scans for potential secrets in staged changes
|
||||||
|
# 2. Creates companion summary files (.sum.md) for discussion files
|
||||||
|
#
|
||||||
|
# Environment Variables:
|
||||||
|
# CDEV_SKIP_HOOK=1 Skip all checks (hook exits immediately)
|
||||||
|
# CDEV_SKIP_SUMMARIES=1 Skip summary file generation
|
||||||
|
#
|
||||||
|
# Safety: Exits on errors to prevent broken commits
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Find and navigate to the git repo root (or current dir if not in a repo) so file paths work correctly regardless of where the commit command is run
|
if [[ -n "${CDEV_SKIP_HOOK:-}" ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Navigate to git repository root so all file paths work correctly
|
||||||
ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo ".")"
|
ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo ".")"
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# CRITICAL: Acquire Hook Execution Lock
|
||||||
|
# ============================================================================
|
||||||
|
# Prevents concurrent hook executions from corrupting Git repository.
|
||||||
|
# Race condition scenario:
|
||||||
|
# - Process A runs `git add file1.md`, computes blob SHA, starts writing to .git/objects/
|
||||||
|
# - Process B runs `git add file2.md` concurrently
|
||||||
|
# - Blob object creation fails, leaving orphaned SHA in index
|
||||||
|
# - Result: "error: invalid object 100644 <SHA> for '<file>'"
|
||||||
|
#
|
||||||
|
# Solution: Use flock to ensure only one hook instance runs at a time.
|
||||||
|
# The lock is automatically released when this script exits.
|
||||||
|
# ============================================================================
|
||||||
|
LOCK_FILE="${ROOT}/.git/hooks/pre-commit.lock"
|
||||||
|
exec 9>"$LOCK_FILE"
|
||||||
|
|
||||||
|
if ! flock -n 9; then
|
||||||
|
echo >&2 "[pre-commit] Another pre-commit hook is running. Waiting for lock..."
|
||||||
|
flock 9 # Block until lock is available
|
||||||
|
echo >&2 "[pre-commit] Lock acquired, continuing..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cleanup: Remove lock file on exit
|
||||||
|
trap 'rm -f "$LOCK_FILE"' EXIT
|
||||||
|
|
||||||
# -------- collect staged files ----------
|
# -------- collect staged files ----------
|
||||||
# Get list of staged added/modified files into STAGED array, exit early if none found
|
|
||||||
mapfile -t STAGED < <(git diff --cached --name-only --diff-filter=AM || true)
|
mapfile -t STAGED < <(git diff --cached --name-only --diff-filter=AM || true)
|
||||||
[ "${#STAGED[@]}" -eq 0 ] && exit 0
|
[ "${#STAGED[@]}" -eq 0 ] && exit 0
|
||||||
|
|
||||||
# -------- tiny secret scan (fast, regex only) ----------
|
# -------- tiny secret scan (fast, regex only) ----------
|
||||||
# Abort commit if staged changes contain potential secrets (api keys, tokens, etc.) matching common patterns
|
# Abort commit if staged changes contain potential secrets matching common patterns
|
||||||
DIFF="$(git diff --cached)"
|
DIFF="$(git diff --cached)"
|
||||||
if echo "$DIFF" | grep -Eqi '(api[_-]?key|secret|access[_-]?token|private[_-]?key)[:=]\s*[A-Za-z0-9_\-]{12,}'; then
|
if echo "$DIFF" | grep -Eqi '(api[_-]?key|secret|access[_-]?token|private[_-]?key)[:=]\s*[A-Za-z0-9_\-]{12,}'; then
|
||||||
echo >&2 "[pre-commit] Possible secret detected in staged changes."
|
echo >&2 "[pre-commit] Possible secret detected in staged changes."
|
||||||
|
|
@ -21,13 +62,13 @@ if echo "$DIFF" | grep -Eqi '(api[_-]?key|secret|access[_-]?token|private[_-]?ke
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# -------- ensure discussion summaries exist (companion files) ----------
|
# -------- ensure discussion summaries exist (companion files) ----------
|
||||||
# Create and auto-stage a summary template file for any discussion file that doesn't already have one
|
if [[ -z "${CDEV_SKIP_SUMMARIES:-}" ]]; then
|
||||||
ensure_summary() {
|
ensure_summary() {
|
||||||
local disc="$1"
|
local disc="$1"
|
||||||
local dir; dir="$(dirname "$disc")"
|
local dir; dir="$(dirname "$disc")"
|
||||||
local sum="$dir/$(basename "$disc" .md).sum.md"
|
local sum="$dir/$(basename "$disc" .md).sum.md"
|
||||||
if [ ! -f "$sum" ]; then
|
if [ ! -f "$sum" ]; then
|
||||||
cat > "$sum" <<'EOF'
|
cat > "$sum" <<'EOF'
|
||||||
# Summary — <Stage Title>
|
# Summary — <Stage Title>
|
||||||
|
|
||||||
<!-- SUMMARY:DECISIONS START -->
|
<!-- SUMMARY:DECISIONS START -->
|
||||||
|
|
@ -68,21 +109,16 @@ READY: 0 • CHANGES: 0 • REJECT: 0
|
||||||
- Design/Plan: ../design/design.md
|
- Design/Plan: ../design/design.md
|
||||||
<!-- SUMMARY:LINKS END -->
|
<!-- SUMMARY:LINKS END -->
|
||||||
EOF
|
EOF
|
||||||
git add "$sum"
|
git add "$sum"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Process each staged discussion file and ensure it has a summary
|
# Process each staged discussion file and ensure it has a summary
|
||||||
for f in "${STAGED[@]}"; do
|
for f in "${STAGED[@]}"; do
|
||||||
case "$f" in
|
case "$f" in
|
||||||
Docs/features/*/discussions/*.discussion.md) ensure_summary "$f";;
|
Docs/features/*/discussions/*.discussion.md) ensure_summary "$f";;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
# -------- future orchestration (non-blocking status) ----------
|
|
||||||
# Run workflow status check if available, but don't block commit if it fails
|
|
||||||
if [ -x "automation/workflow.py" ]; then
|
|
||||||
python3 automation/workflow.py --status || true
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue