@zenuml/core 3.41.4 → 3.41.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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="$(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 /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 /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 /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
@@ -0,0 +1,113 @@
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="$(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
+ get_feature_paths() {
87
+ local repo_root=$(get_repo_root)
88
+ local current_branch=$(get_current_branch)
89
+ local has_git_repo="false"
90
+
91
+ if has_git; then
92
+ has_git_repo="true"
93
+ fi
94
+
95
+ local feature_dir=$(get_feature_dir "$repo_root" "$current_branch")
96
+
97
+ cat <<EOF
98
+ REPO_ROOT='$repo_root'
99
+ CURRENT_BRANCH='$current_branch'
100
+ HAS_GIT='$has_git_repo'
101
+ FEATURE_DIR='$feature_dir'
102
+ FEATURE_SPEC='$feature_dir/spec.md'
103
+ IMPL_PLAN='$feature_dir/plan.md'
104
+ TASKS='$feature_dir/tasks.md'
105
+ RESEARCH='$feature_dir/research.md'
106
+ DATA_MODEL='$feature_dir/data-model.md'
107
+ QUICKSTART='$feature_dir/quickstart.md'
108
+ CONTRACTS_DIR='$feature_dir/contracts'
109
+ EOF
110
+ }
111
+
112
+ check_file() { [[ -f "$1" ]] && echo " ✓ $2" || echo " ✗ $2"; }
113
+ check_dir() { [[ -d "$1" && -n $(ls -A "$1" 2>/dev/null) ]] && echo " ✓ $2" || echo " ✗ $2"; }
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -e
4
+
5
+ JSON_MODE=false
6
+ ARGS=()
7
+ for arg in "$@"; do
8
+ case "$arg" in
9
+ --json) JSON_MODE=true ;;
10
+ --help|-h) echo "Usage: $0 [--json] <feature_description>"; exit 0 ;;
11
+ *) ARGS+=("$arg") ;;
12
+ esac
13
+ done
14
+
15
+ FEATURE_DESCRIPTION="${ARGS[*]}"
16
+ if [ -z "$FEATURE_DESCRIPTION" ]; then
17
+ echo "Usage: $0 [--json] <feature_description>" >&2
18
+ exit 1
19
+ fi
20
+
21
+ # Function to find the repository root by searching for existing project markers
22
+ find_repo_root() {
23
+ local dir="$1"
24
+ while [ "$dir" != "/" ]; do
25
+ if [ -d "$dir/.git" ] || [ -d "$dir/.specify" ]; then
26
+ echo "$dir"
27
+ return 0
28
+ fi
29
+ dir="$(dirname "$dir")"
30
+ done
31
+ return 1
32
+ }
33
+
34
+ # Resolve repository root. Prefer git information when available, but fall back
35
+ # to searching for repository markers so the workflow still functions in repositories that
36
+ # were initialised with --no-git.
37
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
38
+
39
+ if git rev-parse --show-toplevel >/dev/null 2>&1; then
40
+ REPO_ROOT=$(git rev-parse --show-toplevel)
41
+ HAS_GIT=true
42
+ else
43
+ REPO_ROOT="$(find_repo_root "$SCRIPT_DIR")"
44
+ if [ -z "$REPO_ROOT" ]; then
45
+ echo "Error: Could not determine repository root. Please run this script from within the repository." >&2
46
+ exit 1
47
+ fi
48
+ HAS_GIT=false
49
+ fi
50
+
51
+ cd "$REPO_ROOT"
52
+
53
+ SPECS_DIR="$REPO_ROOT/specs"
54
+ mkdir -p "$SPECS_DIR"
55
+
56
+ HIGHEST=0
57
+ if [ -d "$SPECS_DIR" ]; then
58
+ for dir in "$SPECS_DIR"/*; do
59
+ [ -d "$dir" ] || continue
60
+ dirname=$(basename "$dir")
61
+ number=$(echo "$dirname" | grep -o '^[0-9]\+' || echo "0")
62
+ number=$((10#$number))
63
+ if [ "$number" -gt "$HIGHEST" ]; then HIGHEST=$number; fi
64
+ done
65
+ fi
66
+
67
+ NEXT=$((HIGHEST + 1))
68
+ FEATURE_NUM=$(printf "%03d" "$NEXT")
69
+
70
+ BRANCH_NAME=$(echo "$FEATURE_DESCRIPTION" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//')
71
+ WORDS=$(echo "$BRANCH_NAME" | tr '-' '\n' | grep -v '^$' | head -3 | tr '\n' '-' | sed 's/-$//')
72
+ BRANCH_NAME="${FEATURE_NUM}-${WORDS}"
73
+
74
+ if [ "$HAS_GIT" = true ]; then
75
+ git checkout -b "$BRANCH_NAME"
76
+ else
77
+ >&2 echo "[specify] Warning: Git repository not detected; skipped branch creation for $BRANCH_NAME"
78
+ fi
79
+
80
+ FEATURE_DIR="$SPECS_DIR/$BRANCH_NAME"
81
+ mkdir -p "$FEATURE_DIR"
82
+
83
+ TEMPLATE="$REPO_ROOT/.specify/templates/spec-template.md"
84
+ SPEC_FILE="$FEATURE_DIR/spec.md"
85
+ if [ -f "$TEMPLATE" ]; then cp "$TEMPLATE" "$SPEC_FILE"; else touch "$SPEC_FILE"; fi
86
+
87
+ # Set the SPECIFY_FEATURE environment variable for the current session
88
+ export SPECIFY_FEATURE="$BRANCH_NAME"
89
+
90
+ if $JSON_MODE; then
91
+ printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s"}\n' "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM"
92
+ else
93
+ echo "BRANCH_NAME: $BRANCH_NAME"
94
+ echo "SPEC_FILE: $SPEC_FILE"
95
+ echo "FEATURE_NUM: $FEATURE_NUM"
96
+ echo "SPECIFY_FEATURE environment variable set to: $BRANCH_NAME"
97
+ fi
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -e
4
+
5
+ # Parse command line arguments
6
+ JSON_MODE=false
7
+ ARGS=()
8
+
9
+ for arg in "$@"; do
10
+ case "$arg" in
11
+ --json)
12
+ JSON_MODE=true
13
+ ;;
14
+ --help|-h)
15
+ echo "Usage: $0 [--json]"
16
+ echo " --json Output results in JSON format"
17
+ echo " --help Show this help message"
18
+ exit 0
19
+ ;;
20
+ *)
21
+ ARGS+=("$arg")
22
+ ;;
23
+ esac
24
+ done
25
+
26
+ # Get script directory and load common functions
27
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
28
+ source "$SCRIPT_DIR/common.sh"
29
+
30
+ # Get all paths and variables from common functions
31
+ eval $(get_feature_paths)
32
+
33
+ # Check if we're on a proper feature branch (only for git repos)
34
+ check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1
35
+
36
+ # Ensure the feature directory exists
37
+ mkdir -p "$FEATURE_DIR"
38
+
39
+ # Copy plan template if it exists
40
+ TEMPLATE="$REPO_ROOT/.specify/templates/plan-template.md"
41
+ if [[ -f "$TEMPLATE" ]]; then
42
+ cp "$TEMPLATE" "$IMPL_PLAN"
43
+ echo "Copied plan template to $IMPL_PLAN"
44
+ else
45
+ echo "Warning: Plan template not found at $TEMPLATE"
46
+ # Create a basic plan file if template doesn't exist
47
+ touch "$IMPL_PLAN"
48
+ fi
49
+
50
+ # Output results
51
+ if $JSON_MODE; then
52
+ printf '{"FEATURE_SPEC":"%s","IMPL_PLAN":"%s","SPECS_DIR":"%s","BRANCH":"%s","HAS_GIT":"%s"}\n' \
53
+ "$FEATURE_SPEC" "$IMPL_PLAN" "$FEATURE_DIR" "$CURRENT_BRANCH" "$HAS_GIT"
54
+ else
55
+ echo "FEATURE_SPEC: $FEATURE_SPEC"
56
+ echo "IMPL_PLAN: $IMPL_PLAN"
57
+ echo "SPECS_DIR: $FEATURE_DIR"
58
+ echo "BRANCH: $CURRENT_BRANCH"
59
+ echo "HAS_GIT: $HAS_GIT"
60
+ fi