specweave 1.0.174 → 1.0.175

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.
package/CLAUDE.md CHANGED
@@ -1,4 +1,4 @@
1
- <!-- SW:META template="claude" version="1.0.172" sections="header,start,autodetect,metarule,rules,workflow,reflect,context,structure,taskformat,secrets,syncing,testing,tdd,api,limits,troubleshooting,lazyloading,principles,linking,mcp,auto,docs" -->
1
+ <!-- SW:META template="claude" version="1.0.174" sections="header,start,autodetect,metarule,rules,workflow,reflect,context,structure,taskformat,secrets,syncing,testing,tdd,api,limits,troubleshooting,lazyloading,principles,linking,mcp,auto,docs" -->
2
2
 
3
3
  <!-- SW:SECTION:hook-priority version="1.0.171" -->
4
4
  ## ⛔ ABSOLUTE PRIORITY: Hook Instructions Are Mandatory
@@ -50,7 +50,7 @@ Hooks exist to enforce workflow discipline. If you ignore them:
50
50
  **This is non-negotiable. No exceptions. No "just this once".**
51
51
  <!-- SW:END:hook-priority -->
52
52
 
53
- <!-- SW:SECTION:header version="1.0.172" -->
53
+ <!-- SW:SECTION:header version="1.0.174" -->
54
54
  **Framework**: SpecWeave | **Truth**: `spec.md` + `tasks.md`
55
55
  <!-- SW:END:header -->
56
56
 
@@ -108,7 +108,7 @@ plugins/specweave/
108
108
  **Old "commands" are just skills with `disable-model-invocation: true`** - they only respond to explicit `/name` invocation, not keyword detection.
109
109
  <!-- SW:END:claude-code-concepts -->
110
110
 
111
- <!-- SW:SECTION:start version="1.0.172" -->
111
+ <!-- SW:SECTION:start version="1.0.174" -->
112
112
  ## Getting Started
113
113
 
114
114
  **Initial increment**: `0001-project-setup` (auto-created by `specweave init`)
@@ -118,7 +118,7 @@ plugins/specweave/
118
118
  2. **Customize**: Edit spec.md and use for setup tasks
119
119
  <!-- SW:END:start -->
120
120
 
121
- <!-- SW:SECTION:autodetect version="1.0.172" -->
121
+ <!-- SW:SECTION:autodetect version="1.0.174" -->
122
122
  ## Auto-Detection
123
123
 
124
124
  SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
@@ -128,7 +128,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
128
128
  **Opt-out phrases**: "Just brainstorm first" | "Don't plan yet" | "Quick discussion" | "Let's explore ideas"
129
129
  <!-- SW:END:autodetect -->
130
130
 
131
- <!-- SW:SECTION:metarule version="1.0.172" -->
131
+ <!-- SW:SECTION:metarule version="1.0.174" -->
132
132
  ## Meta-Rule: Think-Before-Act
133
133
 
134
134
  **Satisfy dependencies BEFORE dependent operations.**
@@ -139,7 +139,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
139
139
  ```
140
140
  <!-- SW:END:metarule -->
141
141
 
142
- <!-- SW:SECTION:rules version="1.0.172" -->
142
+ <!-- SW:SECTION:rules version="1.0.174" -->
143
143
  ## Rules
144
144
 
145
145
  1. **Files** → `.specweave/increments/####-name/` (see Structure section for details)
@@ -150,7 +150,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
150
150
  6. **⛔ Marketplace refresh**: Use `specweave refresh-marketplace` CLI (not `scripts/refresh-marketplace.sh`)
151
151
  <!-- SW:END:rules -->
152
152
 
153
- <!-- SW:SECTION:workflow version="1.0.172" -->
153
+ <!-- SW:SECTION:workflow version="1.0.174" -->
154
154
  ## Workflow
155
155
 
156
156
  `/sw:increment "X"` → `/sw:do` → `/sw:progress` → `/sw:done 0001`
@@ -170,7 +170,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
170
170
  **Natural language**: "Let's build X" → `/sw:increment` | "What's status?" → `/sw:progress` | "We're done" → `/sw:done` | "Ship while sleeping" → `/sw:auto`
171
171
  <!-- SW:END:workflow -->
172
172
 
173
- <!-- SW:SECTION:reflect version="1.0.172" -->
173
+ <!-- SW:SECTION:reflect version="1.0.174" -->
174
174
  ## Skill Memories
175
175
 
176
176
  SpecWeave learns from corrections. Learnings saved here automatically. Edit or delete as needed.
@@ -183,7 +183,7 @@ SpecWeave learns from corrections. Learnings saved here automatically. Edit or d
183
183
  <!-- Auto-captured by SpecWeave reflect. Edit or delete as needed. -->
184
184
  <!-- Learnings are organized by skill name. User edits override SpecWeave defaults. -->
185
185
 
186
- <!-- SW:SECTION:context version="1.0.172" -->
186
+ <!-- SW:SECTION:context version="1.0.174" -->
187
187
  ## Context
188
188
 
189
189
  **Before implementing**: Check ADRs at `.specweave/docs/internal/architecture/adr/`
@@ -191,7 +191,7 @@ SpecWeave learns from corrections. Learnings saved here automatically. Edit or d
191
191
  **Load context**: `/sw:context <topic>` loads relevant living docs into conversation
192
192
  <!-- SW:END:context -->
193
193
 
194
- <!-- SW:SECTION:structure version="1.0.172" -->
194
+ <!-- SW:SECTION:structure version="1.0.174" -->
195
195
  ## Structure
196
196
 
197
197
  ```
@@ -206,7 +206,7 @@ SpecWeave learns from corrections. Learnings saved here automatically. Edit or d
206
206
  **Everything else → subfolders**: `reports/` | `logs/` | `scripts/` | `backups/`
207
207
  <!-- SW:END:structure -->
208
208
 
209
- <!-- SW:SECTION:taskformat version="1.0.172" -->
209
+ <!-- SW:SECTION:taskformat version="1.0.174" -->
210
210
  ## Task Format
211
211
 
212
212
  ```markdown
@@ -216,7 +216,7 @@ SpecWeave learns from corrections. Learnings saved here automatically. Edit or d
216
216
  ```
217
217
  <!-- SW:END:taskformat -->
218
218
 
219
- <!-- SW:SECTION:secrets version="1.0.172" -->
219
+ <!-- SW:SECTION:secrets version="1.0.174" -->
220
220
  ## Secrets Check
221
221
 
222
222
  **BEFORE CLI tools**: Check existing config first!
@@ -230,7 +230,7 @@ gh auth status
230
230
  **SECURITY**: NEVER use `grep TOKEN .env` without `-q` flag - it exposes credentials in terminal!
231
231
  <!-- SW:END:secrets -->
232
232
 
233
- <!-- SW:SECTION:syncing version="1.0.172" -->
233
+ <!-- SW:SECTION:syncing version="1.0.174" -->
234
234
  ## External Sync (GitHub/JIRA/ADO)
235
235
 
236
236
  **Commands**: `/sw-github:sync {id}` (issues) | `/sw:sync-specs` (living docs only)
@@ -240,7 +240,7 @@ gh auth status
240
240
  **Config**: Set `sync.github.enabled: true` + `canUpdateExternalItems: true` in config.json
241
241
  <!-- SW:END:syncing -->
242
242
 
243
- <!-- SW:SECTION:testing version="1.0.172" -->
243
+ <!-- SW:SECTION:testing version="1.0.174" -->
244
244
  ## Testing
245
245
 
246
246
  BDD in tasks.md | Unit >80% | `.test.ts` (Vitest)
@@ -252,7 +252,7 @@ vi.mock('./module', () => ({ func: mockFn }));
252
252
  ```
253
253
  <!-- SW:END:testing -->
254
254
 
255
- <!-- SW:SECTION:tdd version="1.0.172" -->
255
+ <!-- SW:SECTION:tdd version="1.0.174" -->
256
256
  ## TDD Mode (Test-Driven Development)
257
257
 
258
258
  **When `testing.defaultTestMode: "TDD"` is configured**, follow RED-GREEN-REFACTOR discipline:
@@ -313,7 +313,7 @@ When TDD is enabled, tasks include phase markers:
313
313
  **Rule**: Complete dependencies BEFORE dependent tasks (RED before GREEN).
314
314
  <!-- SW:END:tdd -->
315
315
 
316
- <!-- SW:SECTION:api version="1.0.172" -->
316
+ <!-- SW:SECTION:api version="1.0.174" -->
317
317
  ## API Development (OpenAPI-First)
318
318
 
319
319
  **For API projects only.** Commands: `/sw:api-docs --all` | `--openapi` | `--postman` | `--validate`
@@ -321,13 +321,13 @@ When TDD is enabled, tasks include phase markers:
321
321
  Enable in config: `{"apiDocs":{"enabled":true,"openApiPath":"openapi.yaml"}}`
322
322
  <!-- SW:END:api -->
323
323
 
324
- <!-- SW:SECTION:limits version="1.0.172" -->
324
+ <!-- SW:SECTION:limits version="1.0.174" -->
325
325
  ## Limits
326
326
 
327
327
  **Max 1500 lines/file** — extract before adding
328
328
  <!-- SW:END:limits -->
329
329
 
330
- <!-- SW:SECTION:troubleshooting version="1.0.172" -->
330
+ <!-- SW:SECTION:troubleshooting version="1.0.174" -->
331
331
  ## Troubleshooting
332
332
 
333
333
  | Issue | Fix |
@@ -343,7 +343,7 @@ Enable in config: `{"apiDocs":{"enabled":true,"openApiPath":"openapi.yaml"}}`
343
343
  | Marketplace shows 0 | Normal with auto-load; `/plugin list` shows actual |
344
344
  <!-- SW:END:troubleshooting -->
345
345
 
346
- <!-- SW:SECTION:lazyloading version="1.0.172" -->
346
+ <!-- SW:SECTION:lazyloading version="1.0.174" -->
347
347
  ## Plugin Auto-Loading
348
348
 
349
349
  Plugins load automatically based on project type and keywords. Manual install if needed:
@@ -357,7 +357,7 @@ export SPECWEAVE_DISABLE_AUTO_LOAD=1 # Disable auto-load
357
357
  **Token savings**: Core ~3-5K tokens vs all plugins ~60K+
358
358
  <!-- SW:END:lazyloading -->
359
359
 
360
- <!-- SW:SECTION:principles version="1.0.172" -->
360
+ <!-- SW:SECTION:principles version="1.0.174" -->
361
361
  ## Principles
362
362
 
363
363
  1. **Spec-first**: `/sw:increment` before coding
@@ -366,7 +366,7 @@ export SPECWEAVE_DISABLE_AUTO_LOAD=1 # Disable auto-load
366
366
  4. **Traceable**: All work → specs → ACs
367
367
  <!-- SW:END:principles -->
368
368
 
369
- <!-- SW:SECTION:linking version="1.0.172" -->
369
+ <!-- SW:SECTION:linking version="1.0.174" -->
370
370
  ## Bidirectional Linking
371
371
 
372
372
  Tasks ↔ User Stories auto-linked via AC-IDs: `AC-US1-01` → `US-001`
@@ -374,7 +374,7 @@ Tasks ↔ User Stories auto-linked via AC-IDs: `AC-US1-01` → `US-001`
374
374
  Task format: `**AC**: AC-US1-01, AC-US1-02` (CRITICAL for linking)
375
375
  <!-- SW:END:linking -->
376
376
 
377
- <!-- SW:SECTION:mcp version="1.0.172" -->
377
+ <!-- SW:SECTION:mcp version="1.0.174" -->
378
378
  ## External Services
379
379
 
380
380
  **Priority**: CLI tools first (simpler) → MCP for complex integrations
@@ -396,7 +396,7 @@ claude mcp add --transport stdio postgres -- npx -y @modelcontextprotocol/server
396
396
  MCP supports lazy-loading (auto mode) - tools load on-demand when >10% context.
397
397
  <!-- SW:END:mcp -->
398
398
 
399
- <!-- SW:SECTION:auto version="1.0.172" -->
399
+ <!-- SW:SECTION:auto version="1.0.174" -->
400
400
  ## Auto Mode
401
401
 
402
402
  **Commands**: `/sw:auto` (start) | `/sw:auto-status` (check) | `/sw:cancel-auto` (emergency only)
@@ -413,7 +413,7 @@ MCP supports lazy-loading (auto mode) - tools load on-demand when >10% context.
413
413
  **STOP & ASK** if: Spec conflicts | Task unnecessary | Requirement ambiguous
414
414
  <!-- SW:END:auto -->
415
415
 
416
- <!-- SW:SECTION:docs version="1.0.172" -->
416
+ <!-- SW:SECTION:docs version="1.0.174" -->
417
417
  ## Docs
418
418
 
419
419
  [spec-weave.com](https://spec-weave.com)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specweave",
3
- "version": "1.0.174",
3
+ "version": "1.0.175",
4
4
  "description": "Spec-driven development framework for Claude Code. AI-native workflow with living documentation, intelligent agents, and multilingual support (9 languages). Enterprise-grade traceability with permanent specs and temporary increments.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,20 +1,28 @@
1
1
  #!/bin/bash
2
2
 
3
- # SpecWeave UserPromptSubmit Hook (v1.0.169 - Direct Skill Invocation)
3
+ # SpecWeave UserPromptSubmit Hook (v1.0.175 - Reliable Plugin Detection)
4
4
  # Fires BEFORE user's command executes (prompt-based hook)
5
5
  # Purpose: Auto-load plugins, discipline validation, context injection, instant command execution
6
6
  #
7
7
  # FEATURES:
8
+ # - v1.0.175: CRITICAL FIX - Use installed_plugins.json as SOURCE OF TRUTH
9
+ # * Reads ~/.claude/plugins/installed_plugins.json directly (eliminates false restart warnings)
10
+ # * `claude plugin list` can have timing/buffering issues → unreliable for detection
11
+ # * Primary: check_plugin_installed_from_json() using jq (fast, accurate)
12
+ # * Fallback: `claude plugin list` only if jq unavailable
13
+ # * Post-install verification: re-checks registry after install to confirm success
14
+ # * Increased timeouts: 5s → 10s for CLI operations (reduces timing issues)
15
+ # * Guard against false positives: if install says "success" but not in registry → treat as already installed
8
16
  # - v1.0.169: DIRECT SKILL INVOCATION - Call sw:increment-planner directly (not wrapper)
9
17
  # * Skips 2-level indirection (hook → sw:increment command → sw:increment-planner skill)
10
18
  # * Passes FULL user prompt as args (not just extracted name)
11
19
  # * Uses <system><rules> tags (Claude-trained) instead of custom <mandatory_instruction>
12
20
  # * More concise, imperative instruction text
13
- # - v1.0.167: FIX PLUGIN RESTART WARNING - Use `claude plugin list` BEFORE install
21
+ # - v1.0.167: FIX PLUGIN RESTART WARNING - Use `claude plugin list` BEFORE install (DEPRECATED - had timing issues)
14
22
  # * Claude CLI always outputs "Successfully installed" even when already installed
15
- # * Now calls `claude plugin list` once to get current plugins, then checks against that
16
- # * Skips install for already-installed plugins (faster + no false restart warnings)
17
- # * Only shows restart warning for TRULY new plugin installs
23
+ # * Called `claude plugin list` once to get current plugins, then checked against that
24
+ # * Skipped install for already-installed plugins (faster + no false restart warnings)
25
+ # * ISSUE: `claude plugin list` output unreliable false positives → fixed in v1.0.175
18
26
  # - v1.0.147: SYNC PLUGIN INSTALL - Plugins available for CURRENT prompt!
19
27
  # * Replaced 20s async LLM detection with ~200ms sync `claude plugin install`
20
28
  # * Claude Code hot-reload picks up plugins immediately
@@ -138,6 +146,36 @@ output_approve_with_context() {
138
146
  printf '{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"%s"}}\n' "$escaped"
139
147
  }
140
148
 
149
+ # Helper: Check if plugin is installed by reading installed_plugins.json (v1.0.175)
150
+ # This is the SOURCE OF TRUTH - more reliable than `claude plugin list` which can have timing issues.
151
+ # Args: $1=plugin name (e.g., "sw-frontend"), $2=marketplace (e.g., "specweave")
152
+ # Returns: 0 if installed, 1 if not installed
153
+ check_plugin_installed_from_json() {
154
+ local plugin="$1"
155
+ local marketplace="$2"
156
+ local registry_path="${HOME}/.claude/plugins/installed_plugins.json"
157
+
158
+ # File must exist
159
+ [[ ! -f "$registry_path" ]] && return 1
160
+
161
+ # Must have jq for reliable JSON parsing
162
+ if ! command -v jq >/dev/null 2>&1; then
163
+ return 1 # Fallback to CLI check if jq not available
164
+ fi
165
+
166
+ # Check if plugin exists in registry
167
+ # Format: {"plugins": {"sw-frontend@specweave": [...], ...}}
168
+ local full_name="${plugin}@${marketplace}"
169
+ local has_plugin
170
+ has_plugin=$(jq -r --arg key "$full_name" '.plugins[$key] // null' "$registry_path" 2>/dev/null)
171
+
172
+ if [[ "$has_plugin" != "null" ]] && [[ -n "$has_plugin" ]]; then
173
+ return 0 # Installed
174
+ else
175
+ return 1 # Not installed
176
+ fi
177
+ }
178
+
141
179
  # ==============================================================================
142
180
  # KEYWORD-BASED PLUGIN DETECTION REMOVED (v1.0.159)
143
181
  # ==============================================================================
@@ -291,16 +329,6 @@ if [[ "${SPECWEAVE_DISABLE_AUTO_LOAD:-0}" != "1" ]] && [[ "${SPECWEAVE_DISABLE_H
291
329
  PLUGINS_INSTALLED=""
292
330
  PLUGINS_ALREADY=""
293
331
 
294
- # v1.0.167: Get list of already-installed plugins ONCE via `claude plugin list`
295
- # This is more reliable than parsing internal JSON files
296
- # Format: "sw-frontend@specweave", "context7@claude-plugins-official", etc.
297
- CURRENT_PLUGINS=""
298
- if command -v timeout >/dev/null 2>&1; then
299
- CURRENT_PLUGINS=$(timeout 5 claude plugin list 2>/dev/null | grep -E "^ ❯ " | sed 's/^ ❯ //' || true)
300
- else
301
- CURRENT_PLUGINS=$(claude plugin list 2>/dev/null | grep -E "^ ❯ " | sed 's/^ ❯ //' || true)
302
- fi
303
-
304
332
  for plugin in $DETECTED_PLUGINS; do
305
333
  [[ -z "$plugin" ]] && continue
306
334
 
@@ -312,11 +340,28 @@ if [[ "${SPECWEAVE_DISABLE_AUTO_LOAD:-0}" != "1" ]] && [[ "${SPECWEAVE_DISABLE_H
312
340
  MARKETPLACE="claude-plugins-official"
313
341
  fi
314
342
 
315
- # v1.0.167: Check if plugin is ALREADY installed (from cached list)
343
+ # v1.0.175: Check if plugin is ALREADY installed (SOURCE OF TRUTH)
344
+ # Primary: Check installed_plugins.json (reliable, fast, no timing issues)
345
+ # Fallback: Check `claude plugin list` if jq not available
316
346
  FULL_PLUGIN_NAME="${plugin}@${MARKETPLACE}"
317
347
  ALREADY_INSTALLED=false
318
- if echo "$CURRENT_PLUGINS" | grep -q "^${FULL_PLUGIN_NAME}$"; then
348
+
349
+ # Try JSON registry first (most reliable)
350
+ if check_plugin_installed_from_json "$plugin" "$MARKETPLACE"; then
319
351
  ALREADY_INSTALLED=true
352
+ else
353
+ # Fallback to CLI check (if jq not available or registry file missing)
354
+ # Give it a longer timeout (10s) to reduce timing issues
355
+ CURRENT_PLUGINS=""
356
+ if command -v timeout >/dev/null 2>&1; then
357
+ CURRENT_PLUGINS=$(timeout 10 claude plugin list 2>/dev/null | grep -E "^ ❯ " | sed 's/^ ❯ //' || true)
358
+ else
359
+ CURRENT_PLUGINS=$(claude plugin list 2>/dev/null | grep -E "^ ❯ " | sed 's/^ ❯ //' || true)
360
+ fi
361
+
362
+ if echo "$CURRENT_PLUGINS" | grep -q "^${FULL_PLUGIN_NAME}$"; then
363
+ ALREADY_INSTALLED=true
364
+ fi
320
365
  fi
321
366
 
322
367
  if [[ "$ALREADY_INSTALLED" == "true" ]]; then
@@ -325,15 +370,26 @@ if [[ "${SPECWEAVE_DISABLE_AUTO_LOAD:-0}" != "1" ]] && [[ "${SPECWEAVE_DISABLE_H
325
370
  PLUGINS_ALREADY="${PLUGINS_ALREADY}${plugin}"
326
371
  else
327
372
  # Plugin not installed - install it
373
+ # Use longer timeout (10s) to ensure installation completes
328
374
  if command -v timeout >/dev/null 2>&1; then
329
- OUT=$(timeout 5 claude plugin install "${FULL_PLUGIN_NAME}" 2>&1) || true
375
+ OUT=$(timeout 10 claude plugin install "${FULL_PLUGIN_NAME}" 2>&1) || true
330
376
  else
331
377
  OUT=$(claude plugin install "${FULL_PLUGIN_NAME}" 2>&1) || true
332
378
  fi
333
379
 
334
- if echo "$OUT" | grep -qi "success"; then
335
- [[ -n "$PLUGINS_INSTALLED" ]] && PLUGINS_INSTALLED="$PLUGINS_INSTALLED, "
336
- PLUGINS_INSTALLED="${PLUGINS_INSTALLED}${plugin}"
380
+ # Only mark as installed if we see "success" or "installed" in output
381
+ if echo "$OUT" | grep -qiE "(success|installed)"; then
382
+ # Double-check: verify it actually got installed
383
+ # Re-check the registry to confirm (guard against false positives)
384
+ sleep 0.5 # Brief delay for registry to update
385
+ if check_plugin_installed_from_json "$plugin" "$MARKETPLACE"; then
386
+ [[ -n "$PLUGINS_INSTALLED" ]] && PLUGINS_INSTALLED="$PLUGINS_INSTALLED, "
387
+ PLUGINS_INSTALLED="${PLUGINS_INSTALLED}${plugin}"
388
+ else
389
+ # Install claimed success but plugin not in registry - treat as already installed
390
+ [[ -n "$PLUGINS_ALREADY" ]] && PLUGINS_ALREADY="$PLUGINS_ALREADY, "
391
+ PLUGINS_ALREADY="${PLUGINS_ALREADY}${plugin}"
392
+ fi
337
393
  fi
338
394
  fi
339
395
  done