Skip to content

Commit acb0309

Browse files
committed
fix
1 parent 70de199 commit acb0309

Some content is hidden

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

43 files changed

+3831
-710
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@ dist
1919
.claude/*
2020
codebuddy_usage.md
2121
.coverage
22+
.codebuddy/
23+
.cursor/
24+
.gemini/

.specify/memory/constitution.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<!-- Sync Impact Report for Constitution v1.0.0
2+
Version change: N/A → 1.0.0
3+
Added sections: Core Principles, Development Workflow, Governance
4+
Removed sections: None
5+
Modified principles: None (initial creation)
6+
Added sections: Core Principles, Development Workflow, Governance
7+
Removed sections: None
8+
Templates requiring updates: ✅ updated .specify/templates/plan-template.md (constitution check section)
9+
Follow-up TODOs: None
10+
-->
11+
# Code Assistant Manager Constitution
12+
13+
## Core Principles
14+
15+
### I. Unified Interface
16+
All AI assistant management MUST occur through a single, consistent CLI interface. The `cam` command serves as the universal entry point for installing, configuring, and operating 17+ supported AI assistants. No direct tool interactions allowed - all operations flow through CAM's standardized protocols.
17+
18+
### II. Security First
19+
Enterprise-grade security is non-negotiable. All configurations use secure file-based storage with environment variable support. MCP client implementations eliminate shell injection vulnerabilities. API keys and credentials are never committed to version control.
20+
21+
### III. Test-Driven Development
22+
Every feature implementation MUST follow TDD principles: tests written first, then code to make tests pass. Comprehensive test suite with 1400+ tests required. All changes trigger automated testing before commits.
23+
24+
### IV. Extensibility Framework
25+
CAM MUST maintain a standardized architecture supporting agents, prompts, skills, and plugins. All extensions use markdown-based configurations with YAML front matter. MCP registry provides 381+ pre-configured servers.
26+
27+
### V. Quality Assurance
28+
Automated quality gates enforce code standards: black formatting, flake8 linting, mypy type checking, and security scanning. Pre-commit hooks prevent non-compliant code. Coverage requirements and complexity monitoring ensure maintainability.
29+
30+
## Development Workflow
31+
32+
### Commit Protocol
33+
- Ask for user approval before any git commit and push
34+
- Run complete test suite using `find` command to locate all test files and execute them sequentially
35+
- Documentation-only changes skip testing
36+
- Never commit credentials, keys, or .env files
37+
38+
### Post-Change Validation
39+
After any code changes, reinstall the project using the standard sequence:
40+
```bash
41+
rm -rf dist/*
42+
./install.sh uninstall
43+
./install.sh
44+
cp ~/.config/code-assistant-manager/providers.json.bak ~/.config/code-assistant-manager/providers.json
45+
```
46+
47+
### Quality Gates
48+
- Code formatting: black with 88-character line length
49+
- Linting: flake8 with bugbear, comprehensions, and simplify rules
50+
- Type checking: mypy with strict configuration
51+
- Security: bandit scanning excluding test directories
52+
- Documentation: interrogate with 50% coverage minimum
53+
54+
## Governance
55+
56+
Constitution supersedes all other practices. Amendments require:
57+
1. Clear rationale documented in commit message
58+
2. Version bump following semantic versioning
59+
3. All dependent templates updated if principles change
60+
4. Test suite passes after changes
61+
62+
All PRs/reviews MUST verify constitution compliance. Complexity increases require explicit justification. Use CLAUDE.md for runtime development guidance.
63+
64+
**Version**: 1.0.0 | **Ratified**: 2026-01-02 | **Last Amended**: 2026-01-02
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
#!/usr/bin/env bash
2+
3+
# Consolidated prerequisite checking script
4+
#
5+
# This script provides unified prerequisite checking for Spec-Driven Development workflow.
6+
# It replaces the functionality previously spread across multiple scripts.
7+
#
8+
# Usage: ./check-prerequisites.sh [OPTIONS]
9+
#
10+
# OPTIONS:
11+
# --json Output in JSON format
12+
# --require-tasks Require tasks.md to exist (for implementation phase)
13+
# --include-tasks Include tasks.md in AVAILABLE_DOCS list
14+
# --paths-only Only output path variables (no validation)
15+
# --help, -h Show help message
16+
#
17+
# OUTPUTS:
18+
# JSON mode: {"FEATURE_DIR":"...", "AVAILABLE_DOCS":["..."]}
19+
# Text mode: FEATURE_DIR:... \n AVAILABLE_DOCS: \n ✓/✗ file.md
20+
# Paths only: REPO_ROOT: ... \n BRANCH: ... \n FEATURE_DIR: ... etc.
21+
22+
set -e
23+
24+
# Parse command line arguments
25+
JSON_MODE=false
26+
REQUIRE_TASKS=false
27+
INCLUDE_TASKS=false
28+
PATHS_ONLY=false
29+
30+
for arg in "$@"; do
31+
case "$arg" in
32+
--json)
33+
JSON_MODE=true
34+
;;
35+
--require-tasks)
36+
REQUIRE_TASKS=true
37+
;;
38+
--include-tasks)
39+
INCLUDE_TASKS=true
40+
;;
41+
--paths-only)
42+
PATHS_ONLY=true
43+
;;
44+
--help|-h)
45+
cat << 'EOF'
46+
Usage: check-prerequisites.sh [OPTIONS]
47+
48+
Consolidated prerequisite checking for Spec-Driven Development workflow.
49+
50+
OPTIONS:
51+
--json Output in JSON format
52+
--require-tasks Require tasks.md to exist (for implementation phase)
53+
--include-tasks Include tasks.md in AVAILABLE_DOCS list
54+
--paths-only Only output path variables (no prerequisite validation)
55+
--help, -h Show this help message
56+
57+
EXAMPLES:
58+
# Check task prerequisites (plan.md required)
59+
./check-prerequisites.sh --json
60+
61+
# Check implementation prerequisites (plan.md + tasks.md required)
62+
./check-prerequisites.sh --json --require-tasks --include-tasks
63+
64+
# Get feature paths only (no validation)
65+
./check-prerequisites.sh --paths-only
66+
67+
EOF
68+
exit 0
69+
;;
70+
*)
71+
echo "ERROR: Unknown option '$arg'. Use --help for usage information." >&2
72+
exit 1
73+
;;
74+
esac
75+
done
76+
77+
# Source common functions
78+
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
79+
source "$SCRIPT_DIR/common.sh"
80+
81+
# Get feature paths and validate branch
82+
eval $(get_feature_paths)
83+
check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1
84+
85+
# If paths-only mode, output paths and exit (support JSON + paths-only combined)
86+
if $PATHS_ONLY; then
87+
if $JSON_MODE; then
88+
# Minimal JSON paths payload (no validation performed)
89+
printf '{"REPO_ROOT":"%s","BRANCH":"%s","FEATURE_DIR":"%s","FEATURE_SPEC":"%s","IMPL_PLAN":"%s","TASKS":"%s"}\n' \
90+
"$REPO_ROOT" "$CURRENT_BRANCH" "$FEATURE_DIR" "$FEATURE_SPEC" "$IMPL_PLAN" "$TASKS"
91+
else
92+
echo "REPO_ROOT: $REPO_ROOT"
93+
echo "BRANCH: $CURRENT_BRANCH"
94+
echo "FEATURE_DIR: $FEATURE_DIR"
95+
echo "FEATURE_SPEC: $FEATURE_SPEC"
96+
echo "IMPL_PLAN: $IMPL_PLAN"
97+
echo "TASKS: $TASKS"
98+
fi
99+
exit 0
100+
fi
101+
102+
# Validate required directories and files
103+
if [[ ! -d "$FEATURE_DIR" ]]; then
104+
echo "ERROR: Feature directory not found: $FEATURE_DIR" >&2
105+
echo "Run /speckit.specify first to create the feature structure." >&2
106+
exit 1
107+
fi
108+
109+
if [[ ! -f "$IMPL_PLAN" ]]; then
110+
echo "ERROR: plan.md not found in $FEATURE_DIR" >&2
111+
echo "Run /speckit.plan first to create the implementation plan." >&2
112+
exit 1
113+
fi
114+
115+
# Check for tasks.md if required
116+
if $REQUIRE_TASKS && [[ ! -f "$TASKS" ]]; then
117+
echo "ERROR: tasks.md not found in $FEATURE_DIR" >&2
118+
echo "Run /speckit.tasks first to create the task list." >&2
119+
exit 1
120+
fi
121+
122+
# Build list of available documents
123+
docs=()
124+
125+
# Always check these optional docs
126+
[[ -f "$RESEARCH" ]] && docs+=("research.md")
127+
[[ -f "$DATA_MODEL" ]] && docs+=("data-model.md")
128+
129+
# Check contracts directory (only if it exists and has files)
130+
if [[ -d "$CONTRACTS_DIR" ]] && [[ -n "$(ls -A "$CONTRACTS_DIR" 2>/dev/null)" ]]; then
131+
docs+=("contracts/")
132+
fi
133+
134+
[[ -f "$QUICKSTART" ]] && docs+=("quickstart.md")
135+
136+
# Include tasks.md if requested and it exists
137+
if $INCLUDE_TASKS && [[ -f "$TASKS" ]]; then
138+
docs+=("tasks.md")
139+
fi
140+
141+
# Output results
142+
if $JSON_MODE; then
143+
# Build JSON array of documents
144+
if [[ ${#docs[@]} -eq 0 ]]; then
145+
json_docs="[]"
146+
else
147+
json_docs=$(printf '"%s",' "${docs[@]}")
148+
json_docs="[${json_docs%,}]"
149+
fi
150+
151+
printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s}\n' "$FEATURE_DIR" "$json_docs"
152+
else
153+
# Text output
154+
echo "FEATURE_DIR:$FEATURE_DIR"
155+
echo "AVAILABLE_DOCS:"
156+
157+
# Show status of each potential document
158+
check_file "$RESEARCH" "research.md"
159+
check_file "$DATA_MODEL" "data-model.md"
160+
check_dir "$CONTRACTS_DIR" "contracts/"
161+
check_file "$QUICKSTART" "quickstart.md"
162+
163+
if $INCLUDE_TASKS; then
164+
check_file "$TASKS" "tasks.md"
165+
fi
166+
fi

.specify/scripts/bash/common.sh

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
#!/usr/bin/env bash
2+
# Common functions and variables for all scripts
3+
4+
# Get repository root, with fallback for non-git repositories
5+
get_repo_root() {
6+
if git rev-parse --show-toplevel >/dev/null 2>&1; then
7+
git rev-parse --show-toplevel
8+
else
9+
# Fall back to script location for non-git repos
10+
local script_dir="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11+
(cd "$script_dir/../../.." && pwd)
12+
fi
13+
}
14+
15+
# Get current branch, with fallback for non-git repositories
16+
get_current_branch() {
17+
# First check if SPECIFY_FEATURE environment variable is set
18+
if [[ -n "${SPECIFY_FEATURE:-}" ]]; then
19+
echo "$SPECIFY_FEATURE"
20+
return
21+
fi
22+
23+
# Then check git if available
24+
if git rev-parse --abbrev-ref HEAD >/dev/null 2>&1; then
25+
git rev-parse --abbrev-ref HEAD
26+
return
27+
fi
28+
29+
# For non-git repos, try to find the latest feature directory
30+
local repo_root=$(get_repo_root)
31+
local specs_dir="$repo_root/specs"
32+
33+
if [[ -d "$specs_dir" ]]; then
34+
local latest_feature=""
35+
local highest=0
36+
37+
for dir in "$specs_dir"/*; do
38+
if [[ -d "$dir" ]]; then
39+
local dirname=$(basename "$dir")
40+
if [[ "$dirname" =~ ^([0-9]{3})- ]]; then
41+
local number=${BASH_REMATCH[1]}
42+
number=$((10#$number))
43+
if [[ "$number" -gt "$highest" ]]; then
44+
highest=$number
45+
latest_feature=$dirname
46+
fi
47+
fi
48+
fi
49+
done
50+
51+
if [[ -n "$latest_feature" ]]; then
52+
echo "$latest_feature"
53+
return
54+
fi
55+
fi
56+
57+
echo "main" # Final fallback
58+
}
59+
60+
# Check if we have git available
61+
has_git() {
62+
git rev-parse --show-toplevel >/dev/null 2>&1
63+
}
64+
65+
check_feature_branch() {
66+
local branch="$1"
67+
local has_git_repo="$2"
68+
69+
# For non-git repos, we can't enforce branch naming but still provide output
70+
if [[ "$has_git_repo" != "true" ]]; then
71+
echo "[specify] Warning: Git repository not detected; skipped branch validation" >&2
72+
return 0
73+
fi
74+
75+
if [[ ! "$branch" =~ ^[0-9]{3}- ]]; then
76+
echo "ERROR: Not on a feature branch. Current branch: $branch" >&2
77+
echo "Feature branches should be named like: 001-feature-name" >&2
78+
return 1
79+
fi
80+
81+
return 0
82+
}
83+
84+
get_feature_dir() { echo "$1/specs/$2"; }
85+
86+
# Find feature directory by numeric prefix instead of exact branch match
87+
# This allows multiple branches to work on the same spec (e.g., 004-fix-bug, 004-add-feature)
88+
find_feature_dir_by_prefix() {
89+
local repo_root="$1"
90+
local branch_name="$2"
91+
local specs_dir="$repo_root/specs"
92+
93+
# Extract numeric prefix from branch (e.g., "004" from "004-whatever")
94+
if [[ ! "$branch_name" =~ ^([0-9]{3})- ]]; then
95+
# If branch doesn't have numeric prefix, fall back to exact match
96+
echo "$specs_dir/$branch_name"
97+
return
98+
fi
99+
100+
local prefix="${BASH_REMATCH[1]}"
101+
102+
# Search for directories in specs/ that start with this prefix
103+
local matches=()
104+
if [[ -d "$specs_dir" ]]; then
105+
for dir in "$specs_dir"/"$prefix"-*; do
106+
if [[ -d "$dir" ]]; then
107+
matches+=("$(basename "$dir")")
108+
fi
109+
done
110+
fi
111+
112+
# Handle results
113+
if [[ ${#matches[@]} -eq 0 ]]; then
114+
# No match found - return the branch name path (will fail later with clear error)
115+
echo "$specs_dir/$branch_name"
116+
elif [[ ${#matches[@]} -eq 1 ]]; then
117+
# Exactly one match - perfect!
118+
echo "$specs_dir/${matches[0]}"
119+
else
120+
# Multiple matches - this shouldn't happen with proper naming convention
121+
echo "ERROR: Multiple spec directories found with prefix '$prefix': ${matches[*]}" >&2
122+
echo "Please ensure only one spec directory exists per numeric prefix." >&2
123+
echo "$specs_dir/$branch_name" # Return something to avoid breaking the script
124+
fi
125+
}
126+
127+
get_feature_paths() {
128+
local repo_root=$(get_repo_root)
129+
local current_branch=$(get_current_branch)
130+
local has_git_repo="false"
131+
132+
if has_git; then
133+
has_git_repo="true"
134+
fi
135+
136+
# Use prefix-based lookup to support multiple branches per spec
137+
local feature_dir=$(find_feature_dir_by_prefix "$repo_root" "$current_branch")
138+
139+
cat <<EOF
140+
REPO_ROOT='$repo_root'
141+
CURRENT_BRANCH='$current_branch'
142+
HAS_GIT='$has_git_repo'
143+
FEATURE_DIR='$feature_dir'
144+
FEATURE_SPEC='$feature_dir/spec.md'
145+
IMPL_PLAN='$feature_dir/plan.md'
146+
TASKS='$feature_dir/tasks.md'
147+
RESEARCH='$feature_dir/research.md'
148+
DATA_MODEL='$feature_dir/data-model.md'
149+
QUICKSTART='$feature_dir/quickstart.md'
150+
CONTRACTS_DIR='$feature_dir/contracts'
151+
EOF
152+
}
153+
154+
check_file() { [[ -f "$1" ]] && echo "$2" || echo "$2"; }
155+
check_dir() { [[ -d "$1" && -n $(ls -A "$1" 2>/dev/null) ]] && echo "$2" || echo "$2"; }
156+

0 commit comments

Comments
 (0)