specweave 1.0.261 → 1.0.263
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-plugin/README.md +0 -2
- package/CLAUDE.md +27 -27
- package/bin/specweave.js +14 -85
- package/dist/dashboard/assets/index-Cv1XUAKk.css +1 -0
- package/dist/dashboard/assets/index-DHOztQSu.js +11 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/src/adapters/README.md +1 -1
- package/dist/src/adapters/agents-md-generator.js +1 -1
- package/dist/src/adapters/agents-md-generator.js.map +1 -1
- package/dist/src/adapters/claude/README.md +8 -8
- package/dist/src/adapters/claude/adapter.js +2 -2
- package/dist/src/adapters/claude-md-generator.js +2 -2
- package/dist/src/adapters/claude-md-generator.js.map +1 -1
- package/dist/src/adapters/cursor/README.md +7 -7
- package/dist/src/adapters/generic/README.md +2 -2
- package/dist/src/cli/commands/create-increment.d.ts +1 -1
- package/dist/src/cli/commands/create-increment.js +1 -1
- package/dist/src/cli/commands/update.d.ts.map +1 -1
- package/dist/src/cli/commands/update.js +64 -1
- package/dist/src/cli/commands/update.js.map +1 -1
- package/dist/src/cli/helpers/init/api-docs-config.js +7 -7
- package/dist/src/cli/helpers/init/api-docs-config.js.map +1 -1
- package/dist/src/core/config/types.d.ts +18 -0
- package/dist/src/core/config/types.d.ts.map +1 -1
- package/dist/src/core/config/types.js +4 -0
- package/dist/src/core/config/types.js.map +1 -1
- package/dist/src/core/external-tools/external-items-display.d.ts.map +1 -1
- package/dist/src/core/external-tools/external-items-display.js +1 -11
- package/dist/src/core/external-tools/external-items-display.js.map +1 -1
- package/dist/src/core/increment/increment-archiver.js +1 -1
- package/dist/src/core/increment/increment-archiver.js.map +1 -1
- package/dist/src/core/increment/metadata-manager.js +2 -2
- package/dist/src/core/increment/metadata-manager.js.map +1 -1
- package/dist/src/core/increment/template-creator.d.ts +1 -1
- package/dist/src/core/increment/template-creator.js +4 -4
- package/dist/src/core/lazy-loading/llm-plugin-detector.d.ts +2 -2
- package/dist/src/core/lazy-loading/llm-plugin-detector.d.ts.map +1 -1
- package/dist/src/core/lazy-loading/llm-plugin-detector.js +15 -5
- package/dist/src/core/lazy-loading/llm-plugin-detector.js.map +1 -1
- package/dist/src/core/living-docs/feature-consistency-validator.js +1 -1
- package/dist/src/core/living-docs/feature-consistency-validator.js.map +1 -1
- package/dist/src/core/living-docs/scaffolding/scaffold.js +3 -3
- package/dist/src/core/notifications/command-integration.d.ts.map +1 -1
- package/dist/src/core/notifications/command-integration.js +0 -1
- package/dist/src/core/notifications/command-integration.js.map +1 -1
- package/dist/src/core/reflection/reflect-handler.js +2 -2
- package/dist/src/core/reflection/reflect-handler.js.map +1 -1
- package/dist/src/core/validators/ac-presence-validator.d.ts +1 -1
- package/dist/src/core/validators/ac-presence-validator.js +3 -3
- package/dist/src/core/validators/ac-presence-validator.js.map +1 -1
- package/dist/src/dashboard/server/command-runner.d.ts.map +1 -1
- package/dist/src/dashboard/server/command-runner.js +2 -2
- package/dist/src/dashboard/server/command-runner.js.map +1 -1
- package/dist/src/dashboard/server/dashboard-server.d.ts.map +1 -1
- package/dist/src/dashboard/server/dashboard-server.js +22 -10
- package/dist/src/dashboard/server/dashboard-server.js.map +1 -1
- package/dist/src/dashboard/server/data/dashboard-data-aggregator.d.ts +9 -1
- package/dist/src/dashboard/server/data/dashboard-data-aggregator.d.ts.map +1 -1
- package/dist/src/dashboard/server/data/dashboard-data-aggregator.js +140 -13
- package/dist/src/dashboard/server/data/dashboard-data-aggregator.js.map +1 -1
- package/dist/src/dashboard/server/data/plugin-scanner.d.ts +1 -1
- package/dist/src/dashboard/server/data/plugin-scanner.d.ts.map +1 -1
- package/dist/src/dashboard/server/data/plugin-scanner.js +2 -2
- package/dist/src/dashboard/server/data/plugin-scanner.js.map +1 -1
- package/dist/src/utils/agents-md-compiler.js +1 -1
- package/dist/src/utils/agents-md-compiler.js.map +1 -1
- package/dist/src/utils/find-project-root.d.ts +5 -4
- package/dist/src/utils/find-project-root.d.ts.map +1 -1
- package/dist/src/utils/find-project-root.js +8 -10
- package/dist/src/utils/find-project-root.js.map +1 -1
- package/dist/src/utils/generate-skills-index.js +3 -3
- package/dist/src/utils/notification-constants.js +1 -1
- package/dist/src/utils/notification-constants.js.map +1 -1
- package/package.json +1 -1
- package/plugins/FINAL-AUDIT-RECOMMENDATIONS.md +3 -3
- package/plugins/specweave/PLUGIN.md +0 -22
- package/plugins/specweave/commands/analytics.md +1 -1
- package/plugins/specweave/commands/discrepancies.md +0 -1
- package/plugins/specweave/commands/living-docs.md +0 -1
- package/plugins/specweave/commands/reconcile.md +1 -1
- package/plugins/specweave/hooks/hooks.json +19 -0
- package/plugins/specweave/hooks/pre-compact.sh +39 -0
- package/plugins/specweave/hooks/stop-sync.sh +23 -1
- package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +4 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh +193 -59
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use-analytics.sh +83 -0
- package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +7 -0
- package/plugins/specweave/hooks/v2/guards/spec-template-enforcement-guard.sh +1 -1
- package/plugins/specweave/hooks/v2/handlers/ac-sync-dispatcher.sh +25 -6
- package/plugins/specweave/hooks/v2/handlers/universal-auto-create-dispatcher.sh +21 -3
- package/plugins/specweave/hooks/v2/lib/check-provider-enabled.sh +52 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +2 -2
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -1
- package/plugins/specweave/scripts/track-analytics.sh +4 -0
- package/plugins/specweave/skills/do/SKILL.md +1 -1
- package/plugins/specweave/skills/done/SKILL.md +1 -1
- package/plugins/specweave/skills/framework/SKILL.md +4 -4
- package/plugins/specweave/skills/increment/SKILL.md +192 -25
- package/plugins/specweave/skills/next/SKILL.md +36 -630
- package/plugins/specweave/skills/pm/phases/00-deep-interview.md +2 -2
- package/plugins/specweave/skills/progress-sync/SKILL.md +7 -25
- package/plugins/specweave/skills/spec-generator/SKILL.md +44 -626
- package/plugins/specweave/skills/tdd-green/SKILL.md +10 -798
- package/plugins/specweave/skills/tdd-red/SKILL.md +8 -136
- package/plugins/specweave/skills/tdd-refactor/SKILL.md +15 -147
- package/plugins/specweave-github/hooks/github-auto-create-handler.sh +23 -5
- package/src/templates/AGENTS.md.template +11 -11
- package/src/templates/CLAUDE.md.template +1 -1
- package/dist/dashboard/assets/index-CDl14O5G.css +0 -1
- package/dist/dashboard/assets/index-CmqBqnWd.js +0 -11
- package/plugins/specweave/commands/api-docs.md +0 -672
- package/plugins/specweave/commands/check-hooks.md +0 -241
- package/plugins/specweave/commands/embed-acs.md +0 -445
- package/plugins/specweave/commands/external.md +0 -145
- package/plugins/specweave/commands/import-docs.md +0 -212
- package/plugins/specweave/commands/migrate-config.md +0 -104
- package/plugins/specweave/commands/notifications.md +0 -94
- package/plugins/specweave/commands/plugin-validator.md +0 -429
- package/plugins/specweave/commands/revert-wip-limit.md +0 -82
- package/plugins/specweave/commands/sync-acs.md +0 -342
- package/plugins/specweave/commands/sync-specs.md +0 -339
- package/plugins/specweave/commands/sync-tasks.md +0 -255
- package/plugins/specweave/commands/update-scope.md +0 -351
- package/plugins/specweave/commands/validate-features.md +0 -207
- package/plugins/specweave/skills/archive-increments/SKILL.md +0 -209
- package/plugins/specweave/skills/code-review/SKILL.md +0 -598
- package/plugins/specweave/skills/increment-planner/SKILL.md +0 -238
- package/plugins/specweave/skills/increment-work-router/SKILL.md +0 -562
- package/plugins/specweave/skills/multi-project-spec-mapper/SKILL.md +0 -423
- package/plugins/specweave/skills/pm-closure-validation/SKILL.md +0 -542
- package/plugins/specweave/skills/smart-reopen-detector/SKILL.md +0 -245
- package/plugins/specweave/skills/tdd-orchestrator/SKILL.md +0 -228
- package/plugins/specweave/skills/umbrella-repo-detector/SKILL.md +0 -301
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
# * Key insight: Users shouldn't need to know about LSP to benefit from it
|
|
24
24
|
# - v1.0.177: SKILL CHAINING REMINDER - Add explicit guidance in SKILL FIRST message
|
|
25
25
|
# * "SKILL FIRST" does NOT mean "only one skill"
|
|
26
|
-
# * Shows domain skills to use after sw:increment
|
|
26
|
+
# * Shows domain skills to use after sw:increment
|
|
27
27
|
# * Points to CLAUDE.md "MANDATORY: Skill Chaining" section
|
|
28
28
|
# - v1.0.175: CRITICAL FIX - Use installed_plugins.json as SOURCE OF TRUTH
|
|
29
29
|
# * Reads ~/.claude/plugins/installed_plugins.json directly (eliminates false restart warnings)
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
# * Post-install verification: re-checks registry after install to confirm success
|
|
34
34
|
# * Increased timeouts: 5s → 10s for CLI operations (reduces timing issues)
|
|
35
35
|
# * Guard against false positives: if install says "success" but not in registry → treat as already installed
|
|
36
|
-
# - v1.0.169: DIRECT SKILL INVOCATION - Call sw:increment
|
|
37
|
-
# *
|
|
36
|
+
# - v1.0.169: DIRECT SKILL INVOCATION - Call sw:increment skill directly
|
|
37
|
+
# * Originally skipped wrapper indirection; increment-planner merged into increment in v1.0.261
|
|
38
38
|
# * Passes FULL user prompt as args (not just extracted name)
|
|
39
39
|
# * Uses <system><rules> tags (Claude-trained) instead of custom <mandatory_instruction>
|
|
40
40
|
# * More concise, imperative instruction text
|
|
@@ -192,6 +192,21 @@ EOF
|
|
|
192
192
|
fi
|
|
193
193
|
fi
|
|
194
194
|
|
|
195
|
+
# ==============================================================================
|
|
196
|
+
# PROJECT ROOT DETECTION (walk up to find .specweave/config.json)
|
|
197
|
+
# ==============================================================================
|
|
198
|
+
# MUST run BEFORE any code that uses SW_PROJECT_ROOT (scope guard, logging, etc.)
|
|
199
|
+
# Checks for config.json to distinguish real projects from stale folders.
|
|
200
|
+
SW_PROJECT_ROOT=""
|
|
201
|
+
_swdir="$PWD"
|
|
202
|
+
while [[ "$_swdir" != "/" ]]; do
|
|
203
|
+
if [[ -f "$_swdir/.specweave/config.json" ]]; then
|
|
204
|
+
SW_PROJECT_ROOT="$_swdir"
|
|
205
|
+
break
|
|
206
|
+
fi
|
|
207
|
+
_swdir=$(dirname "$_swdir")
|
|
208
|
+
done
|
|
209
|
+
|
|
195
210
|
# ==============================================================================
|
|
196
211
|
# USER-LEVEL PLUGIN SCOPE GUARD (v1.0.249)
|
|
197
212
|
# ==============================================================================
|
|
@@ -211,16 +226,21 @@ fi
|
|
|
211
226
|
# 4. Uses a daily marker file to avoid running on every prompt
|
|
212
227
|
#
|
|
213
228
|
# Rate limit: runs at most once per day per project (marker in .specweave/state/)
|
|
214
|
-
|
|
229
|
+
# GUARD: Only run if inside a valid SpecWeave project (prevents stale folder creation)
|
|
215
230
|
SCOPE_GUARD_RUN=false
|
|
231
|
+
SCOPE_GUARD_MARKER=""
|
|
216
232
|
|
|
217
|
-
if [[ -
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
233
|
+
if [[ -n "$SW_PROJECT_ROOT" ]]; then
|
|
234
|
+
SCOPE_GUARD_MARKER="$SW_PROJECT_ROOT/.specweave/state/scope-guard.marker"
|
|
235
|
+
|
|
236
|
+
if [[ -f "$SCOPE_GUARD_MARKER" ]]; then
|
|
237
|
+
# Check if marker is from today (skip if already ran today)
|
|
238
|
+
MARKER_DATE=$(cat "$SCOPE_GUARD_MARKER" 2>/dev/null)
|
|
239
|
+
TODAY=$(date +%Y-%m-%d)
|
|
240
|
+
[[ "$MARKER_DATE" != "$TODAY" ]] && SCOPE_GUARD_RUN=true
|
|
241
|
+
else
|
|
242
|
+
SCOPE_GUARD_RUN=true
|
|
243
|
+
fi
|
|
224
244
|
fi
|
|
225
245
|
|
|
226
246
|
if [[ "$SCOPE_GUARD_RUN" == "true" ]] && command -v jq >/dev/null 2>&1 && command -v claude >/dev/null 2>&1; then
|
|
@@ -251,7 +271,7 @@ if [[ "$SCOPE_GUARD_RUN" == "true" ]] && command -v jq >/dev/null 2>&1 && comman
|
|
|
251
271
|
done
|
|
252
272
|
|
|
253
273
|
if [[ -n "$MIGRATED" ]]; then
|
|
254
|
-
echo "[$(date -Iseconds)] scope-guard | migrated user→project: $MIGRATED" >> "$
|
|
274
|
+
echo "[$(date -Iseconds)] scope-guard | migrated user→project: $MIGRATED" >> "$SW_PROJECT_ROOT/.specweave/state/hook.log" 2>/dev/null || true
|
|
255
275
|
fi
|
|
256
276
|
|
|
257
277
|
# CRITICAL FIX: Restore sw@specweave enabled state after uninstall operations
|
|
@@ -263,7 +283,7 @@ if [[ "$SCOPE_GUARD_RUN" == "true" ]] && command -v jq >/dev/null 2>&1 && comman
|
|
|
263
283
|
# Re-enable core plugin (preserves all other settings)
|
|
264
284
|
jq '.enabledPlugins."sw@specweave" = true' "$USER_SETTINGS" > "${USER_SETTINGS}.tmp" 2>/dev/null && \
|
|
265
285
|
mv "${USER_SETTINGS}.tmp" "$USER_SETTINGS" 2>/dev/null || true
|
|
266
|
-
echo "[$(date -Iseconds)] scope-guard | restored sw@specweave enabled state" >> "$
|
|
286
|
+
echo "[$(date -Iseconds)] scope-guard | restored sw@specweave enabled state" >> "$SW_PROJECT_ROOT/.specweave/state/hook.log" 2>/dev/null || true
|
|
267
287
|
fi
|
|
268
288
|
fi
|
|
269
289
|
fi
|
|
@@ -290,18 +310,7 @@ fi
|
|
|
290
310
|
#
|
|
291
311
|
# When both disabled: NO detection, NO LLM calls, fastest response time (~5-7s saved)
|
|
292
312
|
|
|
293
|
-
#
|
|
294
|
-
# PROJECT ROOT DETECTION (walk up to find .specweave/ — prevents folder pollution)
|
|
295
|
-
# ==============================================================================
|
|
296
|
-
SW_PROJECT_ROOT=""
|
|
297
|
-
_swdir="$PWD"
|
|
298
|
-
while [[ "$_swdir" != "/" ]]; do
|
|
299
|
-
if [[ -d "$_swdir/.specweave" ]]; then
|
|
300
|
-
SW_PROJECT_ROOT="$_swdir"
|
|
301
|
-
break
|
|
302
|
-
fi
|
|
303
|
-
_swdir=$(dirname "$_swdir")
|
|
304
|
-
done
|
|
313
|
+
# PROJECT ROOT DETECTION was moved earlier (before scope guard) to prevent stale folder creation
|
|
305
314
|
|
|
306
315
|
# Check config for pluginAutoLoad.enabled, suggestOnly and incrementAssist.enabled settings
|
|
307
316
|
PLUGIN_AUTOLOAD_ENABLED=true
|
|
@@ -453,16 +462,17 @@ check_plugin_installed_from_json() {
|
|
|
453
462
|
#
|
|
454
463
|
# WHEN NOT TO CREATE INCREMENT (action: "none" ONLY):
|
|
455
464
|
# ┌─────────────────────────────────────────────────────────────────────────────┐
|
|
456
|
-
# │ •
|
|
457
|
-
# │ • Exploration: "show me", "
|
|
458
|
-
# │ • Commands: "run tests", "build", "deploy", "commit"
|
|
459
|
-
# │ • Already in workflow: prompt starts with /sw:
|
|
460
|
-
# │ • Chat/greetings: "hello", "thanks", general conversation
|
|
461
|
-
# │ • EXPLICIT OPT-OUT:
|
|
462
|
-
# │
|
|
463
|
-
# │
|
|
464
|
-
# │
|
|
465
|
-
# │
|
|
465
|
+
# │ • Pure questions: "what is X?", "explain Y", "tell me about Z" │
|
|
466
|
+
# │ • Exploration: "show me", "list", "search for" │
|
|
467
|
+
# │ • Commands: "run tests", "build", "deploy", "commit" │
|
|
468
|
+
# │ • Already in workflow: prompt starts with /sw: │
|
|
469
|
+
# │ • Chat/greetings: "hello", "thanks", general conversation │
|
|
470
|
+
# │ • EXPLICIT OPT-OUT: "don't create an increment", "skip workflow" │
|
|
471
|
+
# │ │
|
|
472
|
+
# │ NOTE: These are NOT questions — they are WORK requiring increments: │
|
|
473
|
+
# │ "investigate", "debug", "troubleshoot", "why does X fail", │
|
|
474
|
+
# │ "optimize", "improve", "secure", "audit", "solve", "resolve", │
|
|
475
|
+
# │ "analyze", "root cause", "X is broken", "X keeps failing" │
|
|
466
476
|
# └─────────────────────────────────────────────────────────────────────────────┘
|
|
467
477
|
#
|
|
468
478
|
# STILL SUGGEST INCREMENT (action: "small_fix"):
|
|
@@ -1004,13 +1014,21 @@ if [[ "${SPECWEAVE_DISABLE_AUTO_LOAD:-0}" != "1" ]] && [[ "${SPECWEAVE_DISABLE_H
|
|
|
1004
1014
|
|
|
1005
1015
|
# Check if specweave CLI is available
|
|
1006
1016
|
if command -v specweave >/dev/null 2>&1; then
|
|
1007
|
-
# Setup logging
|
|
1008
|
-
|
|
1009
|
-
|
|
1017
|
+
# Setup logging (use project root, never create dirs at $HOME)
|
|
1018
|
+
if [[ -n "$SW_PROJECT_ROOT" ]]; then
|
|
1019
|
+
LAZY_LOAD_LOG="$SW_PROJECT_ROOT/.specweave/logs/lazy-loading.log"
|
|
1020
|
+
else
|
|
1021
|
+
LAZY_LOAD_LOG="/dev/null"
|
|
1022
|
+
fi
|
|
1010
1023
|
|
|
1011
1024
|
# Per-session cache to avoid redundant LLM calls (30 min TTL)
|
|
1012
|
-
|
|
1013
|
-
|
|
1025
|
+
if [[ -n "$SW_PROJECT_ROOT" ]]; then
|
|
1026
|
+
PROMPT_CACHE_DIR="$SW_PROJECT_ROOT/.specweave/state/prompt-cache"
|
|
1027
|
+
mkdir -p "$PROMPT_CACHE_DIR" 2>/dev/null
|
|
1028
|
+
else
|
|
1029
|
+
PROMPT_CACHE_DIR="${TMPDIR:-/tmp}/specweave-prompt-cache"
|
|
1030
|
+
mkdir -p "$PROMPT_CACHE_DIR" 2>/dev/null
|
|
1031
|
+
fi
|
|
1014
1032
|
PROMPT_HASH=$(echo "$PROMPT" | md5sum 2>/dev/null | cut -c1-16 || md5 -qs "$PROMPT" 2>/dev/null | cut -c1-16 || echo "nohash")
|
|
1015
1033
|
CACHE_FILE="$PROMPT_CACHE_DIR/${PROMPT_HASH}.json"
|
|
1016
1034
|
|
|
@@ -1287,7 +1305,7 @@ Then spawn agent: \`Task({ subagent_type: \"${PRIMARY_PLUGIN}:${PRIMARY_SKILL_NA
|
|
|
1287
1305
|
CMD="/sw:increment"
|
|
1288
1306
|
[[ -n "$INC_NAME" ]] && CMD="/sw:increment \"$INC_NAME\""
|
|
1289
1307
|
|
|
1290
|
-
# v1.0.169
|
|
1308
|
+
# v1.0.169+: Call sw:increment skill directly
|
|
1291
1309
|
# Pass user prompt so skill can extract context
|
|
1292
1310
|
# INC_MANDATORY comes from detect-intent LLM response
|
|
1293
1311
|
if [[ "$INC_MANDATORY" == "true" ]]; then
|
|
@@ -1300,14 +1318,14 @@ Then spawn agent: \`Task({ subagent_type: \"${PRIMARY_PLUGIN}:${PRIMARY_SKILL_NA
|
|
|
1300
1318
|
DEEP_INTERVIEW_MSG=" Assess prompt completeness first — if gaps exist, ask 2-5 targeted questions before calling."
|
|
1301
1319
|
fi
|
|
1302
1320
|
|
|
1303
|
-
MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}SKILL FIRST: \`Skill({ skill: \"sw:increment
|
|
1321
|
+
MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}SKILL FIRST: \`Skill({ skill: \"sw:increment\" })\` — call BEFORE implementation.
|
|
1304
1322
|
Detection: ${INC_REASON} (confidence: ${INC_CONF}).${AGENT_DIRECTIVE}${DEEP_INTERVIEW_MSG}
|
|
1305
|
-
After increment
|
|
1323
|
+
After increment, chain domain skills per tech stack (see CLAUDE.md Skill Chaining)."
|
|
1306
1324
|
output_approve_with_context "$MSG"
|
|
1307
1325
|
exit 0
|
|
1308
1326
|
else
|
|
1309
1327
|
# v1.0.260: Removed prompt embedding to save context budget
|
|
1310
|
-
MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}Increment suggested: \`Skill({ skill: \"sw:increment
|
|
1328
|
+
MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}Increment suggested: \`Skill({ skill: \"sw:increment\" })\` or \`$CMD\`. Reason: $INC_REASON${AGENT_DIRECTIVE}"
|
|
1311
1329
|
output_approve_with_context "$MSG"
|
|
1312
1330
|
exit 0
|
|
1313
1331
|
fi
|
|
@@ -1315,7 +1333,7 @@ After increment-planner, chain domain skills per tech stack (see CLAUDE.md Skill
|
|
|
1315
1333
|
|
|
1316
1334
|
hotfix)
|
|
1317
1335
|
# v1.0.260: Removed prompt embedding to save context budget
|
|
1318
|
-
MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}Hotfix detected: \`Skill({ skill: \"sw:increment
|
|
1336
|
+
MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}Hotfix detected: \`Skill({ skill: \"sw:increment\", args: \"--type=hotfix\" })\`. Reason: $INC_REASON"
|
|
1319
1337
|
output_approve_with_context "$MSG"
|
|
1320
1338
|
exit 0
|
|
1321
1339
|
;;
|
|
@@ -1333,7 +1351,7 @@ After increment-planner, chain domain skills per tech stack (see CLAUDE.md Skill
|
|
|
1333
1351
|
CMD_SMALLFIX="/sw:increment"
|
|
1334
1352
|
[[ -n "$INC_NAME" ]] && CMD_SMALLFIX="/sw:increment \"$INC_NAME\""
|
|
1335
1353
|
|
|
1336
|
-
MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}Small change — consider tracking: \`Skill({ skill: \"sw:increment
|
|
1354
|
+
MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}Small change — consider tracking: \`Skill({ skill: \"sw:increment\" })\` or \`$CMD_SMALLFIX\`. Reason: $INC_REASON${AGENT_DIRECTIVE}"
|
|
1337
1355
|
output_approve_with_context "$MSG"
|
|
1338
1356
|
exit 0
|
|
1339
1357
|
;;
|
|
@@ -1449,23 +1467,52 @@ After increment-planner, chain domain skills per tech stack (see CLAUDE.md Skill
|
|
|
1449
1467
|
# This fallback ONLY handles increment suggestions (not plugin installs).
|
|
1450
1468
|
if [[ "$LLM_DETECTION_FAILED" == "true" && "$INCREMENT_ASSIST_ENABLED" == "true" ]]; then
|
|
1451
1469
|
# Check for implementation-intent keywords
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1470
|
+
# v1.0.261: Expanded from 20 to 65+ keywords across 9 categories:
|
|
1471
|
+
# Original, Investigation, Analysis, Problem-solving, Optimization,
|
|
1472
|
+
# Security, Documentation, DevOps/Data, Structural
|
|
1473
|
+
if echo "$PROMPT" | grep -qiE "(test|component|feature|fix|refactor|setup|configure|integrate|migrate|upgrade|write|style|design|add|create|implement|build|develop|deploy|scaffold|generate|investigate|debug|troubleshoot|diagnose|trace|profile|examine|inspect|reproduce|replicate|analyze|assess|audit|evaluate|benchmark|measure|validate|solve|resolve|address|tackle|determine|optimize|improve|reduce|minimize|eliminate|simplify|streamline|secure|harden|patch|sanitize|encrypt|document|provision|containerize|dockerize|seed|populate|import|export|transform|sync|batch|remove|delete|replace|convert|extract|merge|split|wrap|unwrap|decouple|modularize)"; then
|
|
1474
|
+
# Exclude PURE questions but NOT investigation/work prompts
|
|
1475
|
+
# v1.0.261: "why" and "how" removed — they almost always imply work intent
|
|
1476
|
+
# ("why does X fail" = investigation, "how do I fix X" = work)
|
|
1477
|
+
# Patterns made more specific to avoid false negatives
|
|
1478
|
+
if ! echo "$PROMPT" | grep -qiE "^[[:space:]]*(what is|what are|explain|tell me about|can you explain|does .* support|should I use|is there a|where is|when did|which one)" && \
|
|
1455
1479
|
! echo "$PROMPT" | grep -qE "\?[[:space:]]*$"; then
|
|
1456
1480
|
# v1.0.260: Removed prompt embedding to save context budget
|
|
1457
1481
|
if [[ "$INCREMENT_MANDATORY_CONFIG" == "true" ]]; then
|
|
1458
|
-
FALLBACK_MSG="SKILL FIRST: \`Skill({ skill: \"sw:increment
|
|
1482
|
+
FALLBACK_MSG="SKILL FIRST: \`Skill({ skill: \"sw:increment\" })\` — call BEFORE implementation.
|
|
1459
1483
|
Detection: Implementation keywords detected (LLM unavailable, keyword fallback).
|
|
1460
|
-
After increment
|
|
1484
|
+
After increment, chain domain skills per tech stack (see CLAUDE.md Skill Chaining)."
|
|
1461
1485
|
else
|
|
1462
|
-
FALLBACK_MSG="Increment suggested: \`Skill({ skill: \"sw:increment
|
|
1486
|
+
FALLBACK_MSG="Increment suggested: \`Skill({ skill: \"sw:increment\" })\`. Reason: Implementation keywords detected (LLM unavailable, keyword fallback)."
|
|
1463
1487
|
fi
|
|
1464
1488
|
echo "[$(date -Iseconds)] keyword-fallback | prompt_keywords_matched=true | mandatory=$INCREMENT_MANDATORY_CONFIG" >> "$LAZY_LOAD_LOG"
|
|
1465
1489
|
output_approve_with_context "$FALLBACK_MSG"
|
|
1466
1490
|
exit 0
|
|
1467
1491
|
fi
|
|
1468
1492
|
fi
|
|
1493
|
+
|
|
1494
|
+
# ==================================================================
|
|
1495
|
+
# ERROR-STATE DETECTION: symptom-based prompts (v1.0.261)
|
|
1496
|
+
# ==================================================================
|
|
1497
|
+
# Catches prompts describing failure states without action verbs:
|
|
1498
|
+
# "the dashboard is broken", "login keeps failing", "app crashes on mobile"
|
|
1499
|
+
# Only runs when LLM failed AND primary keyword regex didn't match.
|
|
1500
|
+
if echo "$PROMPT" | grep -qiE "(is broken|keeps? failing|crash(es|ing)|hang(s|ing)|times? out|is slow|memory leak|performance issue|not working|throwing error|exception|stack trace|segfault|deadlock|race condition)"; then
|
|
1501
|
+
# Require 3+ words for context (not just bare "is broken")
|
|
1502
|
+
WORD_COUNT=$(echo "$PROMPT" | wc -w | tr -d ' ')
|
|
1503
|
+
if [[ "$WORD_COUNT" -ge 3 ]]; then
|
|
1504
|
+
if [[ "$INCREMENT_MANDATORY_CONFIG" == "true" ]]; then
|
|
1505
|
+
FALLBACK_MSG="SKILL FIRST: \`Skill({ skill: \"sw:increment\" })\` — call BEFORE implementation.
|
|
1506
|
+
Detection: Error/failure state detected (LLM unavailable, symptom fallback).
|
|
1507
|
+
After increment, chain domain skills per tech stack (see CLAUDE.md Skill Chaining)."
|
|
1508
|
+
else
|
|
1509
|
+
FALLBACK_MSG="Increment suggested: \`Skill({ skill: \"sw:increment\" })\`. Reason: Error/failure state detected (LLM unavailable, symptom fallback)."
|
|
1510
|
+
fi
|
|
1511
|
+
echo "[$(date -Iseconds)] symptom-fallback | prompt_symptom_matched=true | mandatory=$INCREMENT_MANDATORY_CONFIG" >> "$LAZY_LOAD_LOG"
|
|
1512
|
+
output_approve_with_context "$FALLBACK_MSG"
|
|
1513
|
+
exit 0
|
|
1514
|
+
fi
|
|
1515
|
+
fi
|
|
1469
1516
|
fi
|
|
1470
1517
|
fi
|
|
1471
1518
|
fi
|
|
@@ -1565,10 +1612,11 @@ if [[ -n "$SW_PROJECT_ROOT" ]] && [[ -d "$SW_PROJECT_ROOT/.specweave" ]]; then
|
|
|
1565
1612
|
AUTOLOAD_PLUGINS_MSG="$TDD_MSG"
|
|
1566
1613
|
fi
|
|
1567
1614
|
|
|
1568
|
-
# Log TDD activation
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1615
|
+
# Log TDD activation (use project root, never create dirs at $HOME)
|
|
1616
|
+
if [[ -n "$SW_PROJECT_ROOT" ]]; then
|
|
1617
|
+
TDD_LOG="$SW_PROJECT_ROOT/.specweave/logs/tdd-enforcement.log"
|
|
1618
|
+
echo "[$(date -Iseconds)] TDD_MODE=$TDD_MODE | enforcement=$TDD_ENFORCEMENT | source=$TDD_SOURCE" >> "$TDD_LOG" 2>/dev/null
|
|
1619
|
+
fi
|
|
1572
1620
|
fi
|
|
1573
1621
|
fi
|
|
1574
1622
|
|
|
@@ -1592,7 +1640,12 @@ fi
|
|
|
1592
1640
|
# ==============================================================================
|
|
1593
1641
|
# Even if prompt contains SpecWeave keywords, exit if no .specweave directory
|
|
1594
1642
|
# v1.0.144: Still show plugin autoload message for non-SpecWeave projects
|
|
1595
|
-
|
|
1643
|
+
# Use SW_PROJECT_ROOT to avoid creating dirs relative to CWD
|
|
1644
|
+
if [[ -n "$SW_PROJECT_ROOT" ]]; then
|
|
1645
|
+
SPECWEAVE_DIR="$SW_PROJECT_ROOT/.specweave"
|
|
1646
|
+
else
|
|
1647
|
+
SPECWEAVE_DIR=".specweave"
|
|
1648
|
+
fi
|
|
1596
1649
|
if [[ ! -d "$SPECWEAVE_DIR" ]]; then
|
|
1597
1650
|
if [[ -n "$AUTOLOAD_PLUGINS_MSG" ]]; then
|
|
1598
1651
|
# Show plugin loading feedback even for non-SpecWeave projects
|
|
@@ -1937,7 +1990,7 @@ if [[ "$DEEP_INTERVIEW_ENABLED" == "true" ]] && [[ -z "$ACTIVE_INCREMENT" ]]; th
|
|
|
1937
1990
|
fi
|
|
1938
1991
|
|
|
1939
1992
|
if [[ "$HAVE_ACTIVE_STATE" != "true" ]]; then
|
|
1940
|
-
SMART_INTERVIEW_GATE_MSG="No active increment. Assess prompt completeness for complexity — if gaps, ask 2-5 targeted questions. If sufficient, call sw:increment
|
|
1993
|
+
SMART_INTERVIEW_GATE_MSG="No active increment. Assess prompt completeness for complexity — if gaps, ask 2-5 targeted questions. If sufficient, call sw:increment."
|
|
1941
1994
|
fi
|
|
1942
1995
|
fi
|
|
1943
1996
|
|
|
@@ -2174,7 +2227,60 @@ fi
|
|
|
2174
2227
|
# P2 (important): LSP explicit request, WIP/interview gate
|
|
2175
2228
|
# P3 (informational): LSP setup/install suggestions, archive suggestion
|
|
2176
2229
|
|
|
2177
|
-
|
|
2230
|
+
# ==============================================================================
|
|
2231
|
+
# CONTEXT BUDGET RESOLUTION (v1.0.262)
|
|
2232
|
+
# ==============================================================================
|
|
2233
|
+
# 1. Read base level from config.json (contextBudget.level)
|
|
2234
|
+
# 2. If autoAdapt=true, check context-pressure.json and step down
|
|
2235
|
+
# 3. Map level to char budget
|
|
2236
|
+
# 4. Environment override: SPECWEAVE_CONTEXT_BUDGET
|
|
2237
|
+
|
|
2238
|
+
BUDGET_LEVEL="full"
|
|
2239
|
+
AUTO_ADAPT=true
|
|
2240
|
+
if [[ -f "$CONFIG_PATH" ]] && command -v jq >/dev/null 2>&1; then
|
|
2241
|
+
BUDGET_LEVEL=$(jq -r '.contextBudget.level // "full"' "$CONFIG_PATH" 2>/dev/null || echo "full")
|
|
2242
|
+
AUTO_ADAPT_VAL=$(jq -r '.contextBudget.autoAdapt // true' "$CONFIG_PATH" 2>/dev/null || echo "true")
|
|
2243
|
+
[[ "$AUTO_ADAPT_VAL" == "false" ]] && AUTO_ADAPT=false
|
|
2244
|
+
fi
|
|
2245
|
+
|
|
2246
|
+
# Environment override (for quick testing without config changes)
|
|
2247
|
+
[[ -n "${SPECWEAVE_CONTEXT_BUDGET:-}" ]] && BUDGET_LEVEL="$SPECWEAVE_CONTEXT_BUDGET"
|
|
2248
|
+
|
|
2249
|
+
# Auto-adapt: check pressure state from PreCompact hook
|
|
2250
|
+
if [[ "$AUTO_ADAPT" == "true" ]] && [[ -n "$SW_PROJECT_ROOT" ]]; then
|
|
2251
|
+
PRESSURE_FILE="$SW_PROJECT_ROOT/.specweave/state/context-pressure.json"
|
|
2252
|
+
if [[ -f "$PRESSURE_FILE" ]] && command -v jq >/dev/null 2>&1; then
|
|
2253
|
+
PRESSURE_LEVEL=$(jq -r '.level // "normal"' "$PRESSURE_FILE" 2>/dev/null || echo "normal")
|
|
2254
|
+
case "$PRESSURE_LEVEL" in
|
|
2255
|
+
elevated)
|
|
2256
|
+
# Step down one level
|
|
2257
|
+
case "$BUDGET_LEVEL" in
|
|
2258
|
+
full) BUDGET_LEVEL="compact" ;;
|
|
2259
|
+
compact) BUDGET_LEVEL="minimal" ;;
|
|
2260
|
+
esac
|
|
2261
|
+
;;
|
|
2262
|
+
critical)
|
|
2263
|
+
# Jump to minimal regardless of base
|
|
2264
|
+
[[ "$BUDGET_LEVEL" != "off" ]] && BUDGET_LEVEL="minimal"
|
|
2265
|
+
;;
|
|
2266
|
+
esac
|
|
2267
|
+
fi
|
|
2268
|
+
fi
|
|
2269
|
+
|
|
2270
|
+
# Map level to char budget
|
|
2271
|
+
case "$BUDGET_LEVEL" in
|
|
2272
|
+
full) CONTEXT_BUDGET=2500 ;;
|
|
2273
|
+
compact) CONTEXT_BUDGET=1000 ;;
|
|
2274
|
+
minimal) CONTEXT_BUDGET=300 ;;
|
|
2275
|
+
off) CONTEXT_BUDGET=0 ;;
|
|
2276
|
+
*) CONTEXT_BUDGET=2500 ;;
|
|
2277
|
+
esac
|
|
2278
|
+
|
|
2279
|
+
# If budget is 0, skip all context assembly
|
|
2280
|
+
if [[ "$CONTEXT_BUDGET" -eq 0 ]]; then
|
|
2281
|
+
echo '{"decision":"approve"}'
|
|
2282
|
+
exit 0
|
|
2283
|
+
fi
|
|
2178
2284
|
|
|
2179
2285
|
# Helper: Append message to FINAL_MESSAGE if it fits within budget
|
|
2180
2286
|
# Args: $1=message to append
|
|
@@ -2208,6 +2314,34 @@ _budget_append "$LSP_INSTALL_MSG"
|
|
|
2208
2314
|
_budget_append "$LSP_SETUP_SUGGESTION_MSG"
|
|
2209
2315
|
_budget_append "$ARCHIVE_SUGGESTION_MSG"
|
|
2210
2316
|
|
|
2317
|
+
# ==============================================================================
|
|
2318
|
+
# TURN DEDUPLICATION: Skip identical context to save tokens (v1.0.262)
|
|
2319
|
+
# ==============================================================================
|
|
2320
|
+
# If this turn's context is identical to last turn's, don't re-inject it.
|
|
2321
|
+
# Claude already has it in history. Saves ~2500 chars per duplicate turn.
|
|
2322
|
+
if [[ -n "$FINAL_MESSAGE" ]] && [[ -n "$SW_PROJECT_ROOT" ]]; then
|
|
2323
|
+
DEDUP_HASH_FILE="$SW_PROJECT_ROOT/.specweave/state/.context-hash"
|
|
2324
|
+
CURRENT_HASH=""
|
|
2325
|
+
if command -v md5sum >/dev/null 2>&1; then
|
|
2326
|
+
CURRENT_HASH=$(printf '%s' "$FINAL_MESSAGE" | md5sum | cut -d' ' -f1)
|
|
2327
|
+
elif command -v md5 >/dev/null 2>&1; then
|
|
2328
|
+
CURRENT_HASH=$(printf '%s' "$FINAL_MESSAGE" | md5)
|
|
2329
|
+
fi
|
|
2330
|
+
|
|
2331
|
+
if [[ -n "$CURRENT_HASH" ]]; then
|
|
2332
|
+
if [[ -f "$DEDUP_HASH_FILE" ]]; then
|
|
2333
|
+
PREV_HASH=$(cat "$DEDUP_HASH_FILE" 2>/dev/null)
|
|
2334
|
+
if [[ "$CURRENT_HASH" == "$PREV_HASH" ]]; then
|
|
2335
|
+
# Identical to last turn — skip injection
|
|
2336
|
+
echo '{"decision":"approve"}'
|
|
2337
|
+
exit 0
|
|
2338
|
+
fi
|
|
2339
|
+
fi
|
|
2340
|
+
# Save hash for next turn
|
|
2341
|
+
echo "$CURRENT_HASH" > "$DEDUP_HASH_FILE" 2>/dev/null
|
|
2342
|
+
fi
|
|
2343
|
+
fi
|
|
2344
|
+
|
|
2211
2345
|
if [[ -n "$FINAL_MESSAGE" ]]; then
|
|
2212
2346
|
output_approve_with_context "$FINAL_MESSAGE"
|
|
2213
2347
|
else
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# post-tool-use-analytics.sh - Track Skill and Task tool usage for analytics
|
|
3
|
+
#
|
|
4
|
+
# PostToolUse hook for Skill|Task tools (separate from Edit|Write dispatcher)
|
|
5
|
+
# Extracts skill/agent info from stdin JSON and calls track-analytics.sh
|
|
6
|
+
#
|
|
7
|
+
# CRITICAL: Must exit 0, never block, run <5s
|
|
8
|
+
|
|
9
|
+
set +e
|
|
10
|
+
|
|
11
|
+
[[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
|
|
12
|
+
|
|
13
|
+
# Project root detection
|
|
14
|
+
PROJECT_ROOT="$PWD"
|
|
15
|
+
while [[ "$PROJECT_ROOT" != "/" ]] && [[ ! -d "$PROJECT_ROOT/.specweave" ]]; do
|
|
16
|
+
PROJECT_ROOT=$(dirname "$PROJECT_ROOT")
|
|
17
|
+
done
|
|
18
|
+
[[ ! -d "$PROJECT_ROOT/.specweave" ]] && exit 0
|
|
19
|
+
|
|
20
|
+
# Read stdin (tool result JSON)
|
|
21
|
+
INPUT=""
|
|
22
|
+
if command -v gtimeout >/dev/null 2>&1; then
|
|
23
|
+
INPUT=$(gtimeout 1 cat 2>/dev/null || echo '{}')
|
|
24
|
+
elif command -v timeout >/dev/null 2>&1; then
|
|
25
|
+
INPUT=$(timeout 1 cat 2>/dev/null || echo '{}')
|
|
26
|
+
else
|
|
27
|
+
INPUT=$(cat 2>/dev/null || echo '{}')
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
[[ -z "$INPUT" ]] && exit 0
|
|
31
|
+
|
|
32
|
+
# Script paths
|
|
33
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
34
|
+
PLUGIN_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
|
35
|
+
TRACK_SCRIPT="$PLUGIN_ROOT/scripts/track-analytics.sh"
|
|
36
|
+
|
|
37
|
+
[[ ! -f "$TRACK_SCRIPT" ]] && exit 0
|
|
38
|
+
|
|
39
|
+
# Detect active increment for context
|
|
40
|
+
ACTIVE_INCREMENT=""
|
|
41
|
+
CACHE_FILE="$PROJECT_ROOT/.specweave/state/status-line.json"
|
|
42
|
+
if [[ -f "$CACHE_FILE" ]] && command -v jq >/dev/null 2>&1; then
|
|
43
|
+
ACTIVE_INCREMENT=$(jq -r '.incrementId // ""' "$CACHE_FILE" 2>/dev/null || echo "")
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# Extract tool_name
|
|
47
|
+
TOOL_NAME=$(echo "$INPUT" | grep -o '"tool_name"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/')
|
|
48
|
+
|
|
49
|
+
# Fallback: detect tool type from input fields
|
|
50
|
+
if [[ -z "$TOOL_NAME" ]]; then
|
|
51
|
+
if echo "$INPUT" | grep -q '"skill"[[:space:]]*:'; then
|
|
52
|
+
TOOL_NAME="Skill"
|
|
53
|
+
elif echo "$INPUT" | grep -q '"subagent_type"[[:space:]]*:'; then
|
|
54
|
+
TOOL_NAME="Task"
|
|
55
|
+
fi
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
case "$TOOL_NAME" in
|
|
59
|
+
Skill)
|
|
60
|
+
SKILL_NAME=$(echo "$INPUT" | grep -o '"skill"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/')
|
|
61
|
+
[[ -z "$SKILL_NAME" ]] && exit 0
|
|
62
|
+
|
|
63
|
+
# Extract plugin from skill name prefix
|
|
64
|
+
PLUGIN="specweave"
|
|
65
|
+
if [[ "$SKILL_NAME" == *:* ]]; then
|
|
66
|
+
PREFIX="${SKILL_NAME%%:*}"
|
|
67
|
+
if [[ "$PREFIX" != "sw" ]]; then
|
|
68
|
+
PLUGIN="$PREFIX"
|
|
69
|
+
fi
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
bash "$TRACK_SCRIPT" skill "$SKILL_NAME" --plugin "$PLUGIN" --success --increment "$ACTIVE_INCREMENT" 2>/dev/null &
|
|
73
|
+
;;
|
|
74
|
+
|
|
75
|
+
Task)
|
|
76
|
+
AGENT_TYPE=$(echo "$INPUT" | grep -o '"subagent_type"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/')
|
|
77
|
+
[[ -z "$AGENT_TYPE" ]] && AGENT_TYPE="general"
|
|
78
|
+
|
|
79
|
+
bash "$TRACK_SCRIPT" agent "$AGENT_TYPE" --plugin specweave --success --increment "$ACTIVE_INCREMENT" 2>/dev/null &
|
|
80
|
+
;;
|
|
81
|
+
esac
|
|
82
|
+
|
|
83
|
+
exit 0
|
|
@@ -39,6 +39,13 @@ if [[ -f "$AUTO_MODE_FILE" ]]; then
|
|
|
39
39
|
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] SessionStart: Cleared auto-mode session files (session-scoped)" >> "$PROJECT_ROOT/.specweave/logs/session.log" 2>/dev/null
|
|
40
40
|
fi
|
|
41
41
|
|
|
42
|
+
# ============================================================================
|
|
43
|
+
# CONTEXT PRESSURE RESET: Clear pressure state for fresh session budget (v1.0.262)
|
|
44
|
+
# Ensures new sessions start at user's configured base budget level
|
|
45
|
+
# ============================================================================
|
|
46
|
+
rm -f "$STATE_DIR/context-pressure.json" 2>/dev/null
|
|
47
|
+
rm -f "$STATE_DIR/.context-hash" 2>/dev/null
|
|
48
|
+
|
|
42
49
|
# ============================================================================
|
|
43
50
|
# PLUGIN CACHE: Do NOT delete - Claude Code manages its own plugin cache
|
|
44
51
|
# v1.0.206: (REVERTED) Cache deletion broke plugin loading - installed_plugins.json
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
# user stories directly to spec.md without using PM expertise.
|
|
10
10
|
#
|
|
11
11
|
# WORKFLOW ENFORCED:
|
|
12
|
-
# 1. increment
|
|
12
|
+
# 1. increment skill creates TEMPLATE via createIncrementTemplates() API
|
|
13
13
|
# 2. Templates have markers like [Story Title], [user type], etc.
|
|
14
14
|
# 3. User invokes PM skill to complete the template
|
|
15
15
|
# 4. Direct full-content writes are BLOCKED
|
|
@@ -90,9 +90,27 @@ if [[ ! -f "$CONFIG_PATH" ]] || ! command -v jq >/dev/null 2>&1; then
|
|
|
90
90
|
exit 0
|
|
91
91
|
fi
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
# Use shared provider detection (supports PROFILES, LEGACY DIRECT, LEGACY PROVIDER formats)
|
|
94
|
+
HANDLER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
95
|
+
SHARED_LIB="$HANDLER_DIR/../lib/check-provider-enabled.sh"
|
|
96
|
+
if [[ -f "$SHARED_LIB" ]]; then
|
|
97
|
+
source "$SHARED_LIB"
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
GH_ENABLED="false"
|
|
101
|
+
JIRA_ENABLED="false"
|
|
102
|
+
ADO_ENABLED="false"
|
|
103
|
+
|
|
104
|
+
if type check_provider_enabled &>/dev/null; then
|
|
105
|
+
check_provider_enabled "$CONFIG_PATH" "github" && GH_ENABLED="true"
|
|
106
|
+
check_provider_enabled "$CONFIG_PATH" "jira" && JIRA_ENABLED="true"
|
|
107
|
+
check_provider_enabled "$CONFIG_PATH" "ado" && ADO_ENABLED="true"
|
|
108
|
+
else
|
|
109
|
+
# Fallback to legacy jq check if shared lib not available
|
|
110
|
+
GH_ENABLED=$(jq -r '.sync.github.enabled // false' "$CONFIG_PATH" 2>/dev/null)
|
|
111
|
+
JIRA_ENABLED=$(jq -r '.sync.jira.enabled // false' "$CONFIG_PATH" 2>/dev/null)
|
|
112
|
+
ADO_ENABLED=$(jq -r '.sync.ado.enabled // false' "$CONFIG_PATH" 2>/dev/null)
|
|
113
|
+
fi
|
|
96
114
|
|
|
97
115
|
if [[ "$GH_ENABLED" != "true" && "$JIRA_ENABLED" != "true" && "$ADO_ENABLED" != "true" ]]; then
|
|
98
116
|
log "No providers enabled. Skipping."
|
|
@@ -179,15 +197,16 @@ fi
|
|
|
179
197
|
# ============================================================================
|
|
180
198
|
|
|
181
199
|
# Get all US IDs that have external links from metadata.json
|
|
200
|
+
# Reads BOTH new format (externalLinks.github.issues) and old format (github.issues[].userStory)
|
|
182
201
|
AFFECTED_US_IDS="[]"
|
|
183
202
|
if [[ -f "$METADATA_PATH" ]]; then
|
|
184
|
-
# Collect US IDs from all provider external links
|
|
185
203
|
AFFECTED_US_IDS=$(jq -r '
|
|
186
204
|
[
|
|
187
205
|
(.externalLinks.github.issues // {} | keys[]),
|
|
188
206
|
(.externalLinks.jira.userStories // {} | keys[]),
|
|
189
|
-
(.externalLinks.ado.userStories // {} | keys[])
|
|
190
|
-
|
|
207
|
+
(.externalLinks.ado.userStories // {} | keys[]),
|
|
208
|
+
(.github.issues // [] | .[].userStory // empty)
|
|
209
|
+
] | flatten | unique
|
|
191
210
|
' "$METADATA_PATH" 2>/dev/null) || AFFECTED_US_IDS="[]"
|
|
192
211
|
fi
|
|
193
212
|
|
|
@@ -90,9 +90,27 @@ rm -f "$DEBOUNCE_FILE" 2>/dev/null || true
|
|
|
90
90
|
|
|
91
91
|
command -v jq >/dev/null 2>&1 || exit 0
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
# Use shared provider detection (supports PROFILES, LEGACY DIRECT, LEGACY PROVIDER formats)
|
|
94
|
+
HANDLER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
95
|
+
SHARED_LIB="$HANDLER_DIR/../lib/check-provider-enabled.sh"
|
|
96
|
+
if [[ -f "$SHARED_LIB" ]]; then
|
|
97
|
+
source "$SHARED_LIB"
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
GH_ENABLED="false"
|
|
101
|
+
JIRA_ENABLED="false"
|
|
102
|
+
ADO_ENABLED="false"
|
|
103
|
+
|
|
104
|
+
if type check_provider_enabled &>/dev/null; then
|
|
105
|
+
check_provider_enabled "$CONFIG_PATH" "github" && GH_ENABLED="true"
|
|
106
|
+
check_provider_enabled "$CONFIG_PATH" "jira" && JIRA_ENABLED="true"
|
|
107
|
+
check_provider_enabled "$CONFIG_PATH" "ado" && ADO_ENABLED="true"
|
|
108
|
+
else
|
|
109
|
+
# Fallback to legacy jq check if shared lib not available
|
|
110
|
+
GH_ENABLED=$(jq -r '.sync.github.enabled // false' "$CONFIG_PATH" 2>/dev/null)
|
|
111
|
+
JIRA_ENABLED=$(jq -r '.sync.jira.enabled // false' "$CONFIG_PATH" 2>/dev/null)
|
|
112
|
+
ADO_ENABLED=$(jq -r '.sync.ado.enabled // false' "$CONFIG_PATH" 2>/dev/null)
|
|
113
|
+
fi
|
|
96
114
|
|
|
97
115
|
if [[ "$GH_ENABLED" != "true" && "$JIRA_ENABLED" != "true" && "$ADO_ENABLED" != "true" ]]; then
|
|
98
116
|
log "No providers enabled. Skipping."
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# check-provider-enabled.sh - Shared provider config detection for SpecWeave hooks
|
|
3
|
+
#
|
|
4
|
+
# Supports ALL 3 config formats:
|
|
5
|
+
# 1. PROFILES: sync.profiles.*.provider == "github" + canUpdateExternalItems
|
|
6
|
+
# 2. LEGACY DIRECT: sync.github.enabled == true
|
|
7
|
+
# 3. LEGACY PROVIDER: sync.provider == "github" + sync.enabled == true
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# source "path/to/check-provider-enabled.sh"
|
|
11
|
+
# if check_provider_enabled "$CONFIG_PATH" "github"; then
|
|
12
|
+
# echo "GitHub enabled"
|
|
13
|
+
# fi
|
|
14
|
+
#
|
|
15
|
+
# Returns: 0 = enabled, 1 = disabled
|
|
16
|
+
# Reference: github-sync-handler.sh:72-107 (canonical implementation)
|
|
17
|
+
|
|
18
|
+
check_provider_enabled() {
|
|
19
|
+
local config_file="$1"
|
|
20
|
+
local provider="$2"
|
|
21
|
+
|
|
22
|
+
[[ ! -f "$config_file" ]] && return 1
|
|
23
|
+
|
|
24
|
+
# Method 1: PROFILES format (sync.profiles with provider field)
|
|
25
|
+
if grep -q '"profiles"[[:space:]]*:' "$config_file" 2>/dev/null; then
|
|
26
|
+
if grep -q "\"provider\"[[:space:]]*:[[:space:]]*\"$provider\"" "$config_file" 2>/dev/null; then
|
|
27
|
+
# Also check canUpdateExternalItems (required for sync)
|
|
28
|
+
if grep -q '"canUpdateExternalItems"[[:space:]]*:[[:space:]]*true' "$config_file" 2>/dev/null; then
|
|
29
|
+
return 0
|
|
30
|
+
fi
|
|
31
|
+
fi
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# Method 2: LEGACY DIRECT (sync.{provider}.enabled: true)
|
|
35
|
+
if grep -q "\"$provider\"[[:space:]]*:" "$config_file" 2>/dev/null; then
|
|
36
|
+
if grep -A5 "\"$provider\"[[:space:]]*:" "$config_file" 2>/dev/null | grep -q '"enabled"[[:space:]]*:[[:space:]]*true'; then
|
|
37
|
+
return 0
|
|
38
|
+
fi
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Method 3: LEGACY PROVIDER (sync.provider: "provider" + sync.enabled: true)
|
|
42
|
+
# Only check if no profiles section (pure legacy config)
|
|
43
|
+
if ! grep -q '"profiles"[[:space:]]*:' "$config_file" 2>/dev/null; then
|
|
44
|
+
if grep -q "\"provider\"[[:space:]]*:[[:space:]]*\"$provider\"" "$config_file" 2>/dev/null; then
|
|
45
|
+
if grep -q '"sync"' "$config_file" && grep -A2 '"sync"' "$config_file" | grep -q '"enabled"[[:space:]]*:[[:space:]]*true'; then
|
|
46
|
+
return 0
|
|
47
|
+
fi
|
|
48
|
+
fi
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
return 1
|
|
52
|
+
}
|