specweave 1.0.71 → 1.0.72

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.
Files changed (27) hide show
  1. package/dist/src/core/auto/e2e-coverage.d.ts +248 -0
  2. package/dist/src/core/auto/e2e-coverage.d.ts.map +1 -0
  3. package/dist/src/core/auto/e2e-coverage.js +871 -0
  4. package/dist/src/core/auto/e2e-coverage.js.map +1 -0
  5. package/dist/src/core/auto/increment-planner.js +7 -1
  6. package/dist/src/core/auto/increment-planner.js.map +1 -1
  7. package/dist/src/core/auto/index.d.ts +2 -0
  8. package/dist/src/core/auto/index.d.ts.map +1 -1
  9. package/dist/src/core/auto/index.js +4 -0
  10. package/dist/src/core/auto/index.js.map +1 -1
  11. package/dist/src/core/auto/plan-approval.d.ts +104 -0
  12. package/dist/src/core/auto/plan-approval.d.ts.map +1 -0
  13. package/dist/src/core/auto/plan-approval.js +361 -0
  14. package/dist/src/core/auto/plan-approval.js.map +1 -0
  15. package/package.json +1 -1
  16. package/plugins/specweave/commands/auto.md +86 -0
  17. package/plugins/specweave/hooks/lib/resolve-package.sh +126 -0
  18. package/plugins/specweave/hooks/lib/sync-spec-content.sh +47 -3
  19. package/plugins/specweave/hooks/stop-auto.sh +119 -0
  20. package/plugins/specweave/hooks/v2/handlers/github-sync-handler.sh +8 -0
  21. package/plugins/specweave/hooks/v2/handlers/living-docs-handler.sh +10 -3
  22. package/plugins/specweave/hooks/v2/handlers/living-specs-handler.sh +18 -7
  23. package/plugins/specweave/hooks/v2/handlers/project-bridge-handler.sh +10 -3
  24. package/plugins/specweave/hooks/v2/session-end.sh +50 -2
  25. package/plugins/specweave/hooks/v2/session-start.sh +68 -4
  26. package/plugins/specweave/scripts/chunk-prompt.js +204 -0
  27. package/plugins/specweave/scripts/setup-auto.sh +66 -0
@@ -7,9 +7,51 @@
7
7
  #
8
8
  # v0.35.3 - Fixed: use set +e for hook safety
9
9
  # v0.35.x - Fixed: Don't create .specweave in non-project directories
10
+ # v1.0.71 - Fixed: Use specweave package location, not PROJECT_ROOT/dist
10
11
 
11
12
  set +e # CRITICAL: Never use set -e in hooks (causes cascading failures)
12
13
 
14
+ # =============================================================================
15
+ # CRITICAL FIX: Resolve specweave package location for CLI scripts
16
+ # =============================================================================
17
+ HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18
+
19
+ resolve_specweave_package() {
20
+ local hook_dir="$1"
21
+
22
+ # From hooks/v2/ go up 4 levels to package root
23
+ local package_root="$(cd "$hook_dir/../../../.." 2>/dev/null && pwd)"
24
+
25
+ if [[ -d "$package_root/dist/src/cli" ]]; then
26
+ echo "$package_root"
27
+ return 0
28
+ fi
29
+
30
+ # Fallback: Try global npm installation
31
+ local npm_root
32
+ npm_root="$(npm root -g 2>/dev/null)"
33
+ if [[ -d "$npm_root/specweave/dist/src/cli" ]]; then
34
+ echo "$npm_root/specweave"
35
+ return 0
36
+ fi
37
+
38
+ # Fallback: Try which specweave
39
+ local npx_path
40
+ npx_path="$(which specweave 2>/dev/null)"
41
+ if [[ -n "$npx_path" ]]; then
42
+ local bin_dir="$(dirname "$npx_path")"
43
+ local pkg_dir="$(cd "$bin_dir/.." 2>/dev/null && pwd)"
44
+ if [[ -d "$pkg_dir/dist/src/cli" ]]; then
45
+ echo "$pkg_dir"
46
+ return 0
47
+ fi
48
+ fi
49
+
50
+ return 1
51
+ }
52
+
53
+ SPECWEAVE_PKG="$(resolve_specweave_package "$HOOK_DIR")"
54
+
13
55
  # Find project root by searching upward for .specweave/ directory
14
56
  find_specweave_root() {
15
57
  local dir="$1"
@@ -30,10 +72,16 @@ if [[ -z "$PROJECT_ROOT" ]]; then
30
72
  exit 0
31
73
  fi
32
74
 
75
+ # If specweave package not found, exit gracefully
76
+ if [[ -z "$SPECWEAVE_PKG" ]]; then
77
+ echo '{"continue": true}'
78
+ exit 0
79
+ fi
80
+
33
81
  LOG_DIR="${PROJECT_ROOT}/.specweave/logs/sessions"
34
82
 
35
83
  # Find session by current PID
36
- SESSION_INFO=$(node "${PROJECT_ROOT}/dist/src/cli/find-session-by-pid.js" $$ 2>/dev/null || echo "")
84
+ SESSION_INFO=$(node "${SPECWEAVE_PKG}/dist/src/cli/find-session-by-pid.js" $$ 2>/dev/null || echo "")
37
85
 
38
86
  if [ -z "$SESSION_INFO" ]; then
39
87
  # No session found, exit gracefully
@@ -73,7 +121,7 @@ log() {
73
121
  fi
74
122
 
75
123
  # Remove session from registry
76
- if node "${PROJECT_ROOT}/dist/src/cli/remove-session.js" "$SESSION_ID" >> "$LOG_FILE" 2>&1; then
124
+ if node "${SPECWEAVE_PKG}/dist/src/cli/remove-session.js" "$SESSION_ID" >> "$LOG_FILE" 2>&1; then
77
125
  log "Session removed from registry: $SESSION_ID"
78
126
  else
79
127
  log "WARNING: Failed to remove session from registry"
@@ -7,9 +7,64 @@
7
7
  #
8
8
  # v0.35.3 - Fixed: use set +e for hook safety
9
9
  # v0.35.x - Fixed: Don't create .specweave in non-project directories
10
+ # v1.0.71 - Fixed: Use specweave package location, not PROJECT_ROOT/dist
10
11
 
11
12
  set +e # CRITICAL: Never use set -e in hooks (causes cascading failures)
12
13
 
14
+ # =============================================================================
15
+ # CRITICAL FIX: Resolve specweave package location for CLI scripts
16
+ # =============================================================================
17
+ # Problem: Hooks referenced ${PROJECT_ROOT}/dist/src/cli/*.js which doesn't
18
+ # exist on user machines - they only have npm-installed specweave package.
19
+ #
20
+ # Solution: Find the specweave package via:
21
+ # 1. This hook's own location (hooks are inside the package)
22
+ # 2. Global npm root as fallback
23
+ # =============================================================================
24
+
25
+ # Get the directory where this hook script lives
26
+ HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
27
+
28
+ # Resolve specweave package root (hooks are at plugins/specweave/hooks/v2/)
29
+ # Walk up: v2 -> hooks -> specweave -> plugins -> package_root
30
+ resolve_specweave_package() {
31
+ local hook_dir="$1"
32
+
33
+ # From hooks/v2/ go up 4 levels to package root
34
+ local package_root="$(cd "$hook_dir/../../../.." 2>/dev/null && pwd)"
35
+
36
+ # Verify it's a valid specweave package (has dist/src/cli/)
37
+ if [[ -d "$package_root/dist/src/cli" ]]; then
38
+ echo "$package_root"
39
+ return 0
40
+ fi
41
+
42
+ # Fallback: Try global npm installation
43
+ local npm_root
44
+ npm_root="$(npm root -g 2>/dev/null)"
45
+ if [[ -d "$npm_root/specweave/dist/src/cli" ]]; then
46
+ echo "$npm_root/specweave"
47
+ return 0
48
+ fi
49
+
50
+ # Fallback: Try npx resolution
51
+ local npx_path
52
+ npx_path="$(which specweave 2>/dev/null)"
53
+ if [[ -n "$npx_path" ]]; then
54
+ # specweave binary is at package/bin/specweave.js, go up one level
55
+ local bin_dir="$(dirname "$npx_path")"
56
+ local pkg_dir="$(cd "$bin_dir/.." 2>/dev/null && pwd)"
57
+ if [[ -d "$pkg_dir/dist/src/cli" ]]; then
58
+ echo "$pkg_dir"
59
+ return 0
60
+ fi
61
+ fi
62
+
63
+ return 1
64
+ }
65
+
66
+ SPECWEAVE_PKG="$(resolve_specweave_package "$HOOK_DIR")"
67
+
13
68
  # Find project root by searching upward for .specweave/ directory
14
69
  find_specweave_root() {
15
70
  local dir="$1"
@@ -53,13 +108,21 @@ is_ci_mode() {
53
108
  # Main execution
54
109
  {
55
110
  log "SessionStart hook triggered (PID: $$)"
111
+ log "SPECWEAVE_PKG resolved to: ${SPECWEAVE_PKG:-NOT_FOUND}"
112
+
113
+ # If specweave package not found, skip session tracking (non-fatal)
114
+ if [[ -z "$SPECWEAVE_PKG" ]]; then
115
+ log "WARNING: Could not resolve specweave package location - skipping session tracking"
116
+ echo '{"continue": true}'
117
+ exit 0
118
+ fi
56
119
 
57
120
  # Check if CI mode
58
121
  if is_ci_mode; then
59
122
  log "CI/non-interactive mode detected - using simplified tracking"
60
123
 
61
124
  # Register session but skip background processes
62
- if node "${PROJECT_ROOT}/dist/src/cli/register-session.js" "$SESSION_ID" $$ "claude-code" >> "$LOG_FILE" 2>&1; then
125
+ if node "${SPECWEAVE_PKG}/dist/src/cli/register-session.js" "$SESSION_ID" $$ "claude-code" >> "$LOG_FILE" 2>&1; then
63
126
  log "Session registered (CI mode): $SESSION_ID"
64
127
  else
65
128
  log "WARNING: Failed to register session (non-fatal)"
@@ -74,14 +137,15 @@ is_ci_mode() {
74
137
  log "Interactive mode detected - full session tracking enabled"
75
138
 
76
139
  # Register session in registry
77
- if node "${PROJECT_ROOT}/dist/src/cli/register-session.js" "$SESSION_ID" $$ "claude-code" >> "$LOG_FILE" 2>&1; then
140
+ if node "${SPECWEAVE_PKG}/dist/src/cli/register-session.js" "$SESSION_ID" $$ "claude-code" >> "$LOG_FILE" 2>&1; then
78
141
  log "Session registered: $SESSION_ID"
79
142
  else
80
143
  log "WARNING: Failed to register session (non-fatal)"
81
144
  fi
82
145
 
83
146
  # Start heartbeat process in background (detached)
84
- nohup bash "${PROJECT_ROOT}/plugins/specweave/scripts/heartbeat.sh" "$SESSION_ID" \
147
+ # Use SPECWEAVE_PKG for the heartbeat script location
148
+ nohup bash "${SPECWEAVE_PKG}/plugins/specweave/scripts/heartbeat.sh" "$SESSION_ID" \
85
149
  > "${PROJECT_ROOT}/.specweave/logs/heartbeat-${SESSION_ID}.log" 2>&1 &
86
150
 
87
151
  HEARTBEAT_PID=$!
@@ -89,7 +153,7 @@ is_ci_mode() {
89
153
 
90
154
  # Add heartbeat PID to session's child PIDs
91
155
  if [ -n "$HEARTBEAT_PID" ]; then
92
- node "${PROJECT_ROOT}/dist/src/cli/add-child-pid.js" "$SESSION_ID" "$HEARTBEAT_PID" >> "$LOG_FILE" 2>&1 || true
156
+ node "${SPECWEAVE_PKG}/dist/src/cli/add-child-pid.js" "$SESSION_ID" "$HEARTBEAT_PID" >> "$LOG_FILE" 2>&1 || true
93
157
  fi
94
158
 
95
159
  log "SessionStart hook completed successfully"
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Prompt Chunking for Auto Mode
4
+ *
5
+ * Analyzes a prompt and generates an increment plan for user approval.
6
+ *
7
+ * Usage: node chunk-prompt.js "prompt text" [options]
8
+ *
9
+ * Options:
10
+ * --yes Auto-approve plan (skip user approval)
11
+ * --json Output as JSON
12
+ * --project-path Project root path (default: cwd)
13
+ *
14
+ * Exit codes:
15
+ * 0: Success - plan saved to state
16
+ * 1: Error
17
+ * 2: Cancelled by user
18
+ */
19
+
20
+ import fs from 'fs';
21
+ import path from 'path';
22
+ import { fileURLToPath } from 'url';
23
+
24
+ // Resolve project root (look for .specweave directory)
25
+ function findProjectRoot(startDir) {
26
+ let dir = startDir;
27
+ while (dir !== '/') {
28
+ if (fs.existsSync(path.join(dir, '.specweave'))) {
29
+ return dir;
30
+ }
31
+ dir = path.dirname(dir);
32
+ }
33
+ return startDir;
34
+ }
35
+
36
+ // Dynamic import of built modules
37
+ async function loadModules(projectPath) {
38
+ // Try multiple paths for the built modules
39
+ const possiblePaths = [
40
+ path.join(projectPath, 'dist/src/core/auto/prompt-chunker.js'),
41
+ path.join(projectPath, 'node_modules/specweave/dist/src/core/auto/prompt-chunker.js'),
42
+ // For development
43
+ path.join(path.dirname(fileURLToPath(import.meta.url)), '../../../dist/src/core/auto/prompt-chunker.js'),
44
+ ];
45
+
46
+ for (const p of possiblePaths) {
47
+ if (fs.existsSync(p)) {
48
+ const chunker = await import(p);
49
+ const plannerPath = p.replace('prompt-chunker', 'increment-planner');
50
+ const approvalPath = p.replace('prompt-chunker', 'plan-approval');
51
+ const planner = await import(plannerPath);
52
+ const approval = await import(approvalPath);
53
+ return { chunker, planner, approval };
54
+ }
55
+ }
56
+
57
+ throw new Error('Could not find built modules. Run `npm run build` first.');
58
+ }
59
+
60
+ // Parse arguments
61
+ const args = process.argv.slice(2);
62
+ let prompt = '';
63
+ let autoApprove = false;
64
+ let jsonOutput = false;
65
+ let projectPath = process.cwd();
66
+
67
+ for (let i = 0; i < args.length; i++) {
68
+ const arg = args[i];
69
+ if (arg === '--yes' || arg === '-y') {
70
+ autoApprove = true;
71
+ } else if (arg === '--json') {
72
+ jsonOutput = true;
73
+ } else if (arg === '--project-path') {
74
+ projectPath = args[++i];
75
+ } else if (arg === '--help' || arg === '-h') {
76
+ console.log(`
77
+ Prompt Chunking for Auto Mode
78
+
79
+ Usage: node chunk-prompt.js "prompt text" [options]
80
+
81
+ Options:
82
+ --yes, -y Auto-approve plan (skip user approval)
83
+ --json Output as JSON
84
+ --project-path Project root path (default: cwd)
85
+ --help, -h Show this help
86
+
87
+ Examples:
88
+ node chunk-prompt.js "Build e-commerce with auth, products, cart, checkout"
89
+ node chunk-prompt.js "Build dashboard" --yes
90
+ `);
91
+ process.exit(0);
92
+ } else if (!arg.startsWith('-')) {
93
+ prompt = arg;
94
+ }
95
+ }
96
+
97
+ if (!prompt) {
98
+ console.error('Error: No prompt provided');
99
+ console.error('Usage: node chunk-prompt.js "prompt text"');
100
+ process.exit(1);
101
+ }
102
+
103
+ // Find project root
104
+ projectPath = findProjectRoot(projectPath);
105
+
106
+ async function main() {
107
+ try {
108
+ const { chunker, planner, approval } = await loadModules(projectPath);
109
+
110
+ // Analyze prompt
111
+ const analysis = chunker.analyzePrompt(prompt);
112
+
113
+ if (analysis.features.length === 0) {
114
+ console.error('No features detected in prompt. Please provide a more detailed description.');
115
+ process.exit(1);
116
+ }
117
+
118
+ // Plan increments
119
+ const plan = planner.planIncrements(analysis.features);
120
+
121
+ // Validate plan
122
+ const validation = approval.validatePlan(plan);
123
+ if (!validation.valid) {
124
+ console.error('Plan validation failed:');
125
+ for (const issue of validation.issues) {
126
+ console.error(` - ${issue}`);
127
+ }
128
+ process.exit(1);
129
+ }
130
+
131
+ // Display warnings if any
132
+ const warnings = validation.issues.filter(i => i.startsWith('Warning:'));
133
+ if (warnings.length > 0 && !jsonOutput) {
134
+ console.log('\nāš ļø Warnings:');
135
+ for (const warning of warnings) {
136
+ console.log(` ${warning}`);
137
+ }
138
+ }
139
+
140
+ // Output plan
141
+ if (jsonOutput) {
142
+ console.log(JSON.stringify({
143
+ prompt,
144
+ analysis: {
145
+ totalFeatures: analysis.totalFeatures,
146
+ totalComplexity: analysis.totalComplexity,
147
+ recommendedIncrements: analysis.recommendedIncrements,
148
+ },
149
+ plan: {
150
+ increments: plan.increments.map(inc => ({
151
+ id: inc.id,
152
+ name: inc.name,
153
+ estimatedTasks: inc.estimatedTasks,
154
+ features: inc.features.map(f => f.name),
155
+ dependencies: inc.dependencies,
156
+ })),
157
+ totalTasks: plan.totalTasks,
158
+ estimatedDuration: plan.estimatedDuration,
159
+ },
160
+ autoApprove,
161
+ }, null, 2));
162
+ } else {
163
+ // Display formatted plan
164
+ console.log(approval.formatPlanDisplay(plan, {
165
+ showDetails: true,
166
+ showDependencies: true,
167
+ format: 'text',
168
+ }));
169
+
170
+ // Show approval prompt
171
+ if (!autoApprove) {
172
+ console.log(approval.generateApprovalPrompt(plan));
173
+ }
174
+ }
175
+
176
+ // Save plan to state
177
+ approval.savePlanToState(plan, projectPath);
178
+
179
+ // Log approval if auto-approved
180
+ if (autoApprove) {
181
+ approval.logApprovedPlan(plan, projectPath);
182
+ console.log('\nāœ… Plan auto-approved (--yes flag)');
183
+ }
184
+
185
+ // Output increment IDs for shell script consumption
186
+ if (!jsonOutput) {
187
+ console.log('\nšŸ“‹ Generated Increment IDs:');
188
+ for (const inc of plan.increments) {
189
+ console.log(` ${inc.id}`);
190
+ }
191
+ }
192
+
193
+ // Write increment IDs to a temp file for shell script to read
194
+ const idsFile = path.join(projectPath, '.specweave/state/chunked-increments.txt');
195
+ fs.writeFileSync(idsFile, plan.increments.map(i => i.id).join('\n'));
196
+
197
+ process.exit(0);
198
+ } catch (error) {
199
+ console.error('Error:', error.message);
200
+ process.exit(1);
201
+ }
202
+ }
203
+
204
+ main();
@@ -13,6 +13,8 @@
13
13
  # --skip-gates G1,G2 Pre-approve specific gates
14
14
  # --no-increment Skip auto-creation of increments (work on existing only)
15
15
  # --no-inc Alias for --no-increment (short form)
16
+ # --prompt "text" Analyze prompt and create increments (intelligent chunking)
17
+ # --yes Auto-approve increment plan (skip user approval)
16
18
  # -h, --help Show this help
17
19
 
18
20
  set -e
@@ -26,6 +28,8 @@ INCREMENT_IDS=()
26
28
  ALL_BACKLOG=false
27
29
  SKIP_GATES=""
28
30
  NO_INCREMENT=false
31
+ PROMPT=""
32
+ AUTO_APPROVE=false
29
33
 
30
34
  # Parse arguments
31
35
  while [[ $# -gt 0 ]]; do
@@ -62,6 +66,14 @@ while [[ $# -gt 0 ]]; do
62
66
  NO_INCREMENT=true
63
67
  shift
64
68
  ;;
69
+ --prompt)
70
+ PROMPT="$2"
71
+ shift 2
72
+ ;;
73
+ --yes|-y)
74
+ AUTO_APPROVE=true
75
+ shift
76
+ ;;
65
77
  -h|--help)
66
78
  grep '^#' "$0" | grep -v '!/bin/bash' | sed 's/^# //'
67
79
  exit 0
@@ -100,6 +112,60 @@ if [ -f "$SESSION_FILE" ]; then
100
112
  fi
101
113
  fi
102
114
 
115
+ # Handle --prompt (intelligent chunking)
116
+ if [ -n "$PROMPT" ]; then
117
+ echo "🧠 Analyzing prompt for intelligent chunking..."
118
+ echo ""
119
+
120
+ # Find the chunk-prompt.js script
121
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
122
+ CHUNK_SCRIPT="$SCRIPT_DIR/chunk-prompt.js"
123
+
124
+ if [ ! -f "$CHUNK_SCRIPT" ]; then
125
+ echo "āŒ chunk-prompt.js not found at $CHUNK_SCRIPT"
126
+ exit 1
127
+ fi
128
+
129
+ # Run the chunking analysis
130
+ CHUNK_ARGS=("$PROMPT")
131
+ if [ "$AUTO_APPROVE" = "true" ]; then
132
+ CHUNK_ARGS+=("--yes")
133
+ fi
134
+ CHUNK_ARGS+=("--project-path" "$PROJECT_ROOT")
135
+
136
+ if ! node "$CHUNK_SCRIPT" "${CHUNK_ARGS[@]}"; then
137
+ echo "āŒ Prompt chunking failed"
138
+ exit 1
139
+ fi
140
+
141
+ # Read generated increment IDs
142
+ CHUNKED_IDS_FILE="$STATE_DIR/chunked-increments.txt"
143
+ if [ -f "$CHUNKED_IDS_FILE" ]; then
144
+ echo ""
145
+ echo "šŸ“‹ Plan saved. The increments will be created during execution."
146
+ echo ""
147
+
148
+ # If auto-approve, signal that increments need to be created
149
+ if [ "$AUTO_APPROVE" = "true" ]; then
150
+ echo '{"needsIncrementCreation": true, "fromChunking": true, "autoApproved": true, "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' > "$STATE_DIR/auto-needs-increment.json"
151
+ echo "āœ… Plan auto-approved. Ready to create increments."
152
+ else
153
+ echo '{"needsIncrementCreation": true, "fromChunking": true, "autoApproved": false, "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' > "$STATE_DIR/auto-needs-increment.json"
154
+ echo ""
155
+ echo "šŸ’” To proceed:"
156
+ echo " 1. Review the plan above"
157
+ echo " 2. Run /sw:auto again to start execution"
158
+ echo " 3. Or use --yes to auto-approve"
159
+ fi
160
+
161
+ # Exit with code 2 to signal LLM should create increments
162
+ exit 2
163
+ else
164
+ echo "āŒ No increments generated from prompt"
165
+ exit 1
166
+ fi
167
+ fi
168
+
103
169
  # Build increment queue
104
170
  if [ "$ALL_BACKLOG" = "true" ]; then
105
171
  # Find all backlog increments, sorted by priority