specweave 0.17.13 → 0.17.16
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 +456 -0
- package/README.md +38 -1
- package/dist/src/cli/commands/cicd-monitor.d.ts +11 -0
- package/dist/src/cli/commands/cicd-monitor.d.ts.map +1 -0
- package/dist/src/cli/commands/cicd-monitor.js +154 -0
- package/dist/src/cli/commands/cicd-monitor.js.map +1 -0
- package/dist/src/cli/commands/validate-parent-repo.d.ts +8 -0
- package/dist/src/cli/commands/validate-parent-repo.d.ts.map +1 -0
- package/dist/src/cli/commands/validate-parent-repo.js +15 -0
- package/dist/src/cli/commands/validate-parent-repo.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/types.d.ts +5 -0
- package/dist/src/cli/helpers/issue-tracker/types.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/types.js.map +1 -1
- package/dist/src/core/cicd/config-loader.d.ts +21 -0
- package/dist/src/core/cicd/config-loader.d.ts.map +1 -0
- package/dist/src/core/cicd/config-loader.js +190 -0
- package/dist/src/core/cicd/config-loader.js.map +1 -0
- package/dist/src/core/cicd/index.d.ts +12 -0
- package/dist/src/core/cicd/index.d.ts.map +1 -0
- package/dist/src/core/cicd/index.js +18 -0
- package/dist/src/core/cicd/index.js.map +1 -0
- package/dist/src/core/cicd/monitor-service.d.ts +92 -0
- package/dist/src/core/cicd/monitor-service.d.ts.map +1 -0
- package/dist/src/core/cicd/monitor-service.js +132 -0
- package/dist/src/core/cicd/monitor-service.js.map +1 -0
- package/dist/src/core/cicd/notifier.d.ts +102 -0
- package/dist/src/core/cicd/notifier.d.ts.map +1 -0
- package/dist/src/core/cicd/notifier.js +184 -0
- package/dist/src/core/cicd/notifier.js.map +1 -0
- package/dist/src/core/cicd/parent-repo-validator.d.ts +42 -0
- package/dist/src/core/cicd/parent-repo-validator.d.ts.map +1 -0
- package/dist/src/core/cicd/parent-repo-validator.js +201 -0
- package/dist/src/core/cicd/parent-repo-validator.js.map +1 -0
- package/dist/src/core/cicd/state-manager.d.ts +79 -0
- package/dist/src/core/cicd/state-manager.d.ts.map +1 -0
- package/dist/src/core/cicd/state-manager.js +197 -0
- package/dist/src/core/cicd/state-manager.js.map +1 -0
- package/dist/src/core/cicd/types.d.ts +119 -0
- package/dist/src/core/cicd/types.d.ts.map +1 -0
- package/dist/src/core/cicd/types.js +18 -0
- package/dist/src/core/cicd/types.js.map +1 -0
- package/dist/src/core/cicd/workflow-monitor.d.ts +98 -0
- package/dist/src/core/cicd/workflow-monitor.d.ts.map +1 -0
- package/dist/src/core/cicd/workflow-monitor.js +215 -0
- package/dist/src/core/cicd/workflow-monitor.js.map +1 -0
- package/dist/src/core/spec-content-sync.d.ts.map +1 -1
- package/dist/src/core/spec-content-sync.js +14 -6
- package/dist/src/core/spec-content-sync.js.map +1 -1
- package/dist/src/utils/plugin-validator.d.ts +9 -0
- package/dist/src/utils/plugin-validator.d.ts.map +1 -1
- package/dist/src/utils/plugin-validator.js +86 -19
- package/dist/src/utils/plugin-validator.js.map +1 -1
- package/package.json +2 -2
- package/plugins/specweave/agents/pm/AGENT.md +170 -2
- package/plugins/specweave/hooks/post-increment-planning.sh +89 -26
- package/plugins/specweave/hooks/user-prompt-submit.sh +4 -4
- package/plugins/specweave/skills/increment-planner/SKILL.md +15 -10
- package/plugins/specweave/skills/plugin-validator/SKILL.md +16 -13
- package/plugins/specweave-ado/lib/ado-project-detector.js +32 -5
- package/plugins/specweave-ado/lib/ado-project-detector.ts +44 -5
- package/src/templates/AGENTS.md.template +55 -1
- package/src/templates/CLAUDE.md.template +51 -1
|
@@ -646,33 +646,96 @@ EOF
|
|
|
646
646
|
|
|
647
647
|
translate_living_docs_specs "$increment_id"
|
|
648
648
|
|
|
649
|
-
# 7. Increment-level GitHub
|
|
649
|
+
# 7. Increment-level GitHub issue creation (for single-repo projects)
|
|
650
650
|
log_info ""
|
|
651
|
-
log_info "
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
651
|
+
log_info "🔗 Checking GitHub issue auto-creation..."
|
|
652
|
+
|
|
653
|
+
# Check if auto-create is enabled in config
|
|
654
|
+
local auto_create=$(cat "$CONFIG_FILE" 2>/dev/null | grep -A 5 '"sync"' | grep -A 2 '"settings"' | grep -o '"autoCreateIssue"[[:space:]]*:[[:space:]]*\(true\|false\)' | grep -o '\(true\|false\)' || echo "false")
|
|
655
|
+
|
|
656
|
+
log_debug "Auto-create GitHub issue: $auto_create"
|
|
657
|
+
|
|
658
|
+
if [ "$auto_create" = "true" ]; then
|
|
659
|
+
log_info " 📦 Auto-create enabled, checking for GitHub CLI..."
|
|
660
|
+
|
|
661
|
+
# Check if gh CLI is available
|
|
662
|
+
if ! command -v gh >/dev/null 2>&1; then
|
|
663
|
+
log_info " ⚠️ GitHub CLI (gh) not found, skipping issue creation"
|
|
664
|
+
log_debug "Install: https://cli.github.com/"
|
|
665
|
+
else
|
|
666
|
+
log_info " ✓ GitHub CLI found"
|
|
667
|
+
log_info ""
|
|
668
|
+
log_info "🚀 Creating GitHub issue for $increment_id..."
|
|
669
|
+
|
|
670
|
+
# Create issue (non-blocking)
|
|
671
|
+
if create_github_issue "$increment_id" "$increment_dir"; then
|
|
672
|
+
log_info " ✅ GitHub issue created successfully"
|
|
673
|
+
else
|
|
674
|
+
log_info " ⚠️ GitHub issue creation failed (non-blocking)"
|
|
675
|
+
log_debug "Issue creation failed, but continuing execution"
|
|
676
|
+
fi
|
|
677
|
+
fi
|
|
678
|
+
else
|
|
679
|
+
log_debug "Auto-create disabled in config"
|
|
680
|
+
fi
|
|
681
|
+
|
|
682
|
+
# ============================================================================
|
|
683
|
+
# FALLBACK METADATA CREATION (v0.14.0+)
|
|
684
|
+
# ============================================================================
|
|
685
|
+
# CRITICAL: Ensure metadata.json exists even if GitHub integration failed
|
|
686
|
+
# This prevents silent failures where increment appears complete but lacks metadata
|
|
687
|
+
|
|
688
|
+
log_info ""
|
|
689
|
+
log_info "🔍 Validating metadata.json existence..."
|
|
690
|
+
|
|
691
|
+
local metadata_file="$increment_dir/metadata.json"
|
|
692
|
+
|
|
693
|
+
if [ ! -f "$metadata_file" ]; then
|
|
694
|
+
log_info " ⚠️ metadata.json not found (hook may have failed)"
|
|
695
|
+
log_info " 📝 Creating minimal metadata as fallback..."
|
|
696
|
+
|
|
697
|
+
local current_timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
698
|
+
|
|
699
|
+
# Extract type from spec.md frontmatter (if available)
|
|
700
|
+
local increment_type="feature"
|
|
701
|
+
if [ -f "$spec_file" ]; then
|
|
702
|
+
local extracted_type=$(awk '/^---$/,/^---$/ {if (/^type:/) {sub(/^type:[[:space:]]*"?/, ""); sub(/"?[[:space:]]*$/, ""); print; exit}}' "$spec_file" 2>/dev/null)
|
|
703
|
+
if [ -n "$extracted_type" ]; then
|
|
704
|
+
increment_type="$extracted_type"
|
|
705
|
+
fi
|
|
706
|
+
fi
|
|
707
|
+
|
|
708
|
+
# Create minimal metadata.json
|
|
709
|
+
cat > "$metadata_file" <<EOF_MINIMAL
|
|
710
|
+
{
|
|
711
|
+
"id": "$increment_id",
|
|
712
|
+
"status": "active",
|
|
713
|
+
"type": "$increment_type",
|
|
714
|
+
"created": "$current_timestamp",
|
|
715
|
+
"lastActivity": "$current_timestamp"
|
|
716
|
+
}
|
|
717
|
+
EOF_MINIMAL
|
|
718
|
+
|
|
719
|
+
log_info " ✅ Created minimal metadata.json"
|
|
720
|
+
log_info " ⚠️ Note: No GitHub issue linked"
|
|
721
|
+
log_info " 💡 Run /specweave-github:create-issue $increment_id to create one manually"
|
|
722
|
+
else
|
|
723
|
+
log_info " ✅ metadata.json exists"
|
|
724
|
+
|
|
725
|
+
# Check if GitHub issue was created
|
|
726
|
+
local has_github=$(cat "$metadata_file" 2>/dev/null | grep -o '"github"[[:space:]]*:[[:space:]]*{' || echo "")
|
|
727
|
+
if [ -n "$has_github" ]; then
|
|
728
|
+
local issue_num=$(cat "$metadata_file" 2>/dev/null | grep -o '"issue"[[:space:]]*:[[:space:]]*[0-9]*' | grep -o '[0-9]*' || echo "")
|
|
729
|
+
if [ -n "$issue_num" ]; then
|
|
730
|
+
log_info " ✅ GitHub issue #$issue_num linked"
|
|
731
|
+
fi
|
|
732
|
+
else
|
|
733
|
+
log_debug " ℹ️ No GitHub issue linked (autoCreateIssue may be disabled)"
|
|
734
|
+
fi
|
|
735
|
+
fi
|
|
736
|
+
|
|
737
|
+
# Note: Spec-level sync (SPECS → GitHub Projects/JIRA Epics) is handled separately
|
|
738
|
+
# See: /specweave-github:sync-spec, /specweave-jira:sync-spec, /specweave-ado:sync-spec
|
|
676
739
|
|
|
677
740
|
# 8. Sync spec content to external tools (if configured)
|
|
678
741
|
log_info ""
|
|
@@ -30,7 +30,7 @@ if echo "$PROMPT" | grep -q "/specweave:increment"; then
|
|
|
30
30
|
# Check active increments using MetadataManager
|
|
31
31
|
ACTIVE_COUNT=$(node -e "
|
|
32
32
|
try {
|
|
33
|
-
const { MetadataManager } = require('./dist/core/increment/metadata-manager.js');
|
|
33
|
+
const { MetadataManager } = require('./dist/src/core/increment/metadata-manager.js');
|
|
34
34
|
const active = MetadataManager.getActive();
|
|
35
35
|
console.log(active.length);
|
|
36
36
|
} catch (e) {
|
|
@@ -44,7 +44,7 @@ if echo "$PROMPT" | grep -q "/specweave:increment"; then
|
|
|
44
44
|
# Get list of active increments for error message
|
|
45
45
|
ACTIVE_LIST=$(node -e "
|
|
46
46
|
try {
|
|
47
|
-
const { MetadataManager } = require('./dist/core/increment/metadata-manager.js');
|
|
47
|
+
const { MetadataManager } = require('./dist/src/core/increment/metadata-manager.js');
|
|
48
48
|
const active = MetadataManager.getActive();
|
|
49
49
|
active.forEach(inc => console.log(' - ' + inc.id + ' [' + inc.type + ']'));
|
|
50
50
|
} catch (e) {}
|
|
@@ -64,7 +64,7 @@ EOF
|
|
|
64
64
|
# Get list of active increments for warning
|
|
65
65
|
ACTIVE_LIST=$(node -e "
|
|
66
66
|
try {
|
|
67
|
-
const { MetadataManager } = require('./dist/core/increment/metadata-manager.js');
|
|
67
|
+
const { MetadataManager } = require('./dist/src/core/increment/metadata-manager.js');
|
|
68
68
|
const active = MetadataManager.getActive();
|
|
69
69
|
active.forEach(inc => console.log(' - ' + inc.id + ' [' + inc.type + ']'));
|
|
70
70
|
} catch (e) {}
|
|
@@ -231,7 +231,7 @@ if [[ -d ".specweave/increments" ]]; then
|
|
|
231
231
|
# Get status line from cache (ultra-fast)
|
|
232
232
|
STATUS_LINE=$(node -e "
|
|
233
233
|
try {
|
|
234
|
-
const { StatusLineManager } = require('./dist/core/status-line/status-line-manager.js');
|
|
234
|
+
const { StatusLineManager } = require('./dist/src/core/status-line/status-line-manager.js');
|
|
235
235
|
const manager = new StatusLineManager(process.cwd());
|
|
236
236
|
const result = manager.render();
|
|
237
237
|
console.log(result || '');
|
|
@@ -110,13 +110,15 @@ This skill activates automatically when users say:
|
|
|
110
110
|
|
|
111
111
|
---
|
|
112
112
|
|
|
113
|
-
## 🆕 Multi-Project Support (v0.8.0+)
|
|
113
|
+
## 🆕 Multi-Project Support (v0.8.0+ | Flattened v0.16.11+)
|
|
114
114
|
|
|
115
115
|
**Key Changes**:
|
|
116
|
-
-
|
|
117
|
-
-
|
|
118
|
-
-
|
|
116
|
+
- ✅ **CORRECT** (v0.16.11+): Specs organized with FLATTENED structure: `.specweave/docs/internal/specs/{project-id}/`
|
|
117
|
+
- ❌ **OLD** (v0.8.0-v0.16.10): `.specweave/docs/internal/projects/{project-id}/specs/` (DEPRECATED nested structure)
|
|
118
|
+
- Use `ProjectManager` (from `src/core/project-manager.ts`) to get correct paths (always returns flattened structure)
|
|
119
|
+
- Single project uses `specs/default/` automatically (transparent)
|
|
119
120
|
- Multi-project mode allows multiple teams/repos
|
|
121
|
+
- Parent repo content goes to `specs/_parent/` (for multi-repo setups with parent repositories)
|
|
120
122
|
|
|
121
123
|
**Path Resolution**:
|
|
122
124
|
```typescript
|
|
@@ -177,7 +179,7 @@ Task(
|
|
|
177
179
|
1. Spec (living docs - SOURCE OF TRUTH, permanent):
|
|
178
180
|
- IMPORTANT: Use ProjectManager to get correct path for active project
|
|
179
181
|
- Create at: {projectManager.getSpecsPath()}/spec-{number}-{name}.md
|
|
180
|
-
(This resolves to
|
|
182
|
+
(This resolves to specs/{activeProject}/ with FLATTENED structure v0.16.11+)
|
|
181
183
|
- This is the COMPLETE, PERMANENT source of truth
|
|
182
184
|
- Include ALL of:
|
|
183
185
|
* User stories (US-001, US-002, etc.) with full details
|
|
@@ -299,17 +301,20 @@ STEP 6: Validate Living Docs and Increment Files
|
|
|
299
301
|
|
|
300
302
|
#### Living Spec (Living Docs - Source of Truth) ✅
|
|
301
303
|
```
|
|
302
|
-
.specweave/docs/internal/
|
|
304
|
+
.specweave/docs/internal/specs/{project-id}/ # ← FLATTENED structure (v0.16.11+)
|
|
303
305
|
└── spec-{number}-{name}.md # ← PM Agent (MANDATORY)
|
|
304
306
|
# COMPLETE user stories, AC, requirements
|
|
305
307
|
# This is the PERMANENT source of truth
|
|
306
308
|
# Can be linked to Jira/ADO/GitHub Issues
|
|
307
309
|
# Persists after increment completes
|
|
308
310
|
|
|
309
|
-
# Examples:
|
|
310
|
-
# Single project:
|
|
311
|
-
# Multi-project:
|
|
312
|
-
#
|
|
311
|
+
# Examples (v0.16.11+ Flattened):
|
|
312
|
+
# Single project: specs/default/spec-001-user-auth.md
|
|
313
|
+
# Multi-project: specs/web-app/spec-001-user-auth.md
|
|
314
|
+
# specs/mobile/spec-001-push-notifications.md
|
|
315
|
+
# Parent repo: specs/_parent/spec-002-system-architecture.md
|
|
316
|
+
|
|
317
|
+
# OLD (v0.8.0-v0.16.10): projects/default/specs/... ← DEPRECATED
|
|
313
318
|
```
|
|
314
319
|
|
|
315
320
|
#### Strategy Docs (Optional, High-Level) ⚠️
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: plugin-validator
|
|
3
|
-
description:
|
|
3
|
+
description: Validates SpecWeave plugin installation when EXPLICITLY requested by user. Ensures marketplace registered, core plugin installed, and context-specific plugins available. ONLY activates for explicit validation requests - does NOT auto-activate for workflow commands to avoid false positives. Activates ONLY for plugin validation, environment setup, validate plugins, check plugins, specweave init, fresh setup, marketplace registration.
|
|
4
4
|
allowed-tools: Read, Bash, Grep
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Plugin Validator Skill
|
|
8
8
|
|
|
9
|
-
**Purpose**:
|
|
9
|
+
**Purpose**: Validate and install SpecWeave plugins when explicitly requested by the user.
|
|
10
10
|
|
|
11
|
-
**
|
|
11
|
+
**Activation**: Triggers ONLY when user explicitly requests plugin validation (e.g., "validate plugins", "check plugins", or runs `specweave validate-plugins` command). Does NOT auto-activate for workflow commands to prevent false positive errors.
|
|
12
12
|
|
|
13
13
|
## What This Skill Does
|
|
14
14
|
|
|
@@ -24,16 +24,19 @@ This skill ensures that your SpecWeave environment is properly configured with a
|
|
|
24
24
|
|
|
25
25
|
## When This Skill Activates
|
|
26
26
|
|
|
27
|
-
✅ **
|
|
28
|
-
- You
|
|
29
|
-
- You mention "
|
|
30
|
-
- You
|
|
31
|
-
- You
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
27
|
+
✅ **ONLY activates when explicitly requested**:
|
|
28
|
+
- You mention "plugin validation" or "validate plugins"
|
|
29
|
+
- You mention "environment setup" or "check plugins"
|
|
30
|
+
- You run: `specweave validate-plugins`
|
|
31
|
+
- You ask: "Can you validate my plugins?"
|
|
32
|
+
- You report: "I'm getting plugin errors"
|
|
33
|
+
- During: `specweave init` (initial setup only)
|
|
34
|
+
|
|
35
|
+
❌ **Does NOT auto-activate for**:
|
|
36
|
+
- `/specweave:increment` commands
|
|
37
|
+
- `/specweave:do` commands
|
|
38
|
+
- Any other workflow commands
|
|
39
|
+
- Reason: Prevents false positive errors when plugins are installed but detection fails
|
|
37
40
|
|
|
38
41
|
## Validation Process
|
|
39
42
|
|
|
@@ -233,15 +233,15 @@ class AdoProjectDetector {
|
|
|
233
233
|
*/
|
|
234
234
|
async detectFromContent(content) {
|
|
235
235
|
const candidates = this.analyzeContent(content);
|
|
236
|
-
if (candidates[0]?.confidence
|
|
236
|
+
if (candidates[0]?.confidence >= 0.7) {
|
|
237
237
|
return {
|
|
238
238
|
primary: candidates[0].project,
|
|
239
239
|
confidence: candidates[0].confidence,
|
|
240
240
|
strategy: this.strategy
|
|
241
241
|
};
|
|
242
242
|
}
|
|
243
|
-
if (candidates[0]?.confidence
|
|
244
|
-
const secondary = candidates.slice(1).filter((c) => c.confidence
|
|
243
|
+
if (candidates[0]?.confidence >= 0.4) {
|
|
244
|
+
const secondary = candidates.slice(1).filter((c) => c.confidence >= 0.3).map((c) => c.project);
|
|
245
245
|
return {
|
|
246
246
|
primary: candidates[0].project,
|
|
247
247
|
secondary: secondary.length > 0 ? secondary : void 0,
|
|
@@ -306,7 +306,7 @@ class AdoProjectDetector {
|
|
|
306
306
|
*/
|
|
307
307
|
async detectMultiProject(content) {
|
|
308
308
|
const candidates = this.analyzeContent(content);
|
|
309
|
-
const significantProjects = candidates.filter((c) => c.confidence
|
|
309
|
+
const significantProjects = candidates.filter((c) => c.confidence >= 0.3);
|
|
310
310
|
if (significantProjects.length === 0) {
|
|
311
311
|
return {
|
|
312
312
|
primary: this.availableProjects[0] || "Unknown",
|
|
@@ -328,11 +328,38 @@ class AdoProjectDetector {
|
|
|
328
328
|
*/
|
|
329
329
|
mapToAreaPath(content, project) {
|
|
330
330
|
const areaPaths = process.env.AZURE_DEVOPS_AREA_PATHS?.split(",").map((a) => a.trim()) || [];
|
|
331
|
+
const lowerContent = content.toLowerCase();
|
|
331
332
|
for (const areaPath of areaPaths) {
|
|
332
|
-
if (
|
|
333
|
+
if (lowerContent.includes(areaPath.toLowerCase())) {
|
|
333
334
|
return `${project}\\${areaPath}`;
|
|
334
335
|
}
|
|
335
336
|
}
|
|
337
|
+
const areaPathKeywordMap = {
|
|
338
|
+
"Frontend": ["WebApp", "frontend"],
|
|
339
|
+
"Backend": ["backend", "api", "server"],
|
|
340
|
+
"Mobile": ["MobileApp", "mobile", "ios", "android"],
|
|
341
|
+
"Infrastructure": ["Platform", "infrastructure"],
|
|
342
|
+
"Data": ["DataService", "data", "analytics"]
|
|
343
|
+
};
|
|
344
|
+
let bestMatch = { areaPath: "", confidence: 0 };
|
|
345
|
+
for (const areaPath of areaPaths) {
|
|
346
|
+
const relatedTypes = areaPathKeywordMap[areaPath] || [areaPath];
|
|
347
|
+
let matchCount = 0;
|
|
348
|
+
for (const projectType of relatedTypes) {
|
|
349
|
+
const keywords = this.projectKeywords[projectType] || [];
|
|
350
|
+
for (const keyword of keywords) {
|
|
351
|
+
if (lowerContent.includes(keyword.toLowerCase())) {
|
|
352
|
+
matchCount++;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (matchCount > bestMatch.confidence) {
|
|
357
|
+
bestMatch = { areaPath, confidence: matchCount };
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (bestMatch.confidence >= 2) {
|
|
361
|
+
return `${project}\\${bestMatch.areaPath}`;
|
|
362
|
+
}
|
|
336
363
|
return project;
|
|
337
364
|
}
|
|
338
365
|
/**
|
|
@@ -202,7 +202,7 @@ export class AdoProjectDetector {
|
|
|
202
202
|
const candidates = this.analyzeContent(content);
|
|
203
203
|
|
|
204
204
|
// High confidence: Auto-select
|
|
205
|
-
if (candidates[0]?.confidence
|
|
205
|
+
if (candidates[0]?.confidence >= 0.7) {
|
|
206
206
|
return {
|
|
207
207
|
primary: candidates[0].project,
|
|
208
208
|
confidence: candidates[0].confidence,
|
|
@@ -211,10 +211,10 @@ export class AdoProjectDetector {
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
// Medium confidence: Primary with secondary projects
|
|
214
|
-
if (candidates[0]?.confidence
|
|
214
|
+
if (candidates[0]?.confidence >= 0.4) {
|
|
215
215
|
const secondary = candidates
|
|
216
216
|
.slice(1)
|
|
217
|
-
.filter(c => c.confidence
|
|
217
|
+
.filter(c => c.confidence >= 0.3)
|
|
218
218
|
.map(c => c.project);
|
|
219
219
|
|
|
220
220
|
return {
|
|
@@ -299,7 +299,7 @@ export class AdoProjectDetector {
|
|
|
299
299
|
const candidates = this.analyzeContent(content);
|
|
300
300
|
|
|
301
301
|
// Get all projects with meaningful confidence
|
|
302
|
-
const significantProjects = candidates.filter(c => c.confidence
|
|
302
|
+
const significantProjects = candidates.filter(c => c.confidence >= 0.3);
|
|
303
303
|
|
|
304
304
|
if (significantProjects.length === 0) {
|
|
305
305
|
return {
|
|
@@ -330,13 +330,52 @@ export class AdoProjectDetector {
|
|
|
330
330
|
*/
|
|
331
331
|
mapToAreaPath(content: string, project: string): string {
|
|
332
332
|
const areaPaths = process.env.AZURE_DEVOPS_AREA_PATHS?.split(',').map(a => a.trim()) || [];
|
|
333
|
+
const lowerContent = content.toLowerCase();
|
|
333
334
|
|
|
335
|
+
// First try exact area path name match
|
|
334
336
|
for (const areaPath of areaPaths) {
|
|
335
|
-
if (
|
|
337
|
+
if (lowerContent.includes(areaPath.toLowerCase())) {
|
|
336
338
|
return `${project}\\${areaPath}`;
|
|
337
339
|
}
|
|
338
340
|
}
|
|
339
341
|
|
|
342
|
+
// Try keyword-based detection using PROJECT_KEYWORDS
|
|
343
|
+
// Map area paths to common project types
|
|
344
|
+
const areaPathKeywordMap: { [key: string]: string[] } = {
|
|
345
|
+
'Frontend': ['WebApp', 'frontend'],
|
|
346
|
+
'Backend': ['backend', 'api', 'server'],
|
|
347
|
+
'Mobile': ['MobileApp', 'mobile', 'ios', 'android'],
|
|
348
|
+
'Infrastructure': ['Platform', 'infrastructure'],
|
|
349
|
+
'Data': ['DataService', 'data', 'analytics']
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
let bestMatch = { areaPath: '', confidence: 0 };
|
|
353
|
+
|
|
354
|
+
for (const areaPath of areaPaths) {
|
|
355
|
+
// Get related project types for this area path
|
|
356
|
+
const relatedTypes = areaPathKeywordMap[areaPath] || [areaPath];
|
|
357
|
+
let matchCount = 0;
|
|
358
|
+
|
|
359
|
+
for (const projectType of relatedTypes) {
|
|
360
|
+
// Check if this project type has keywords defined
|
|
361
|
+
const keywords = this.projectKeywords[projectType] || [];
|
|
362
|
+
for (const keyword of keywords) {
|
|
363
|
+
if (lowerContent.includes(keyword.toLowerCase())) {
|
|
364
|
+
matchCount++;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
if (matchCount > bestMatch.confidence) {
|
|
370
|
+
bestMatch = { areaPath, confidence: matchCount };
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Return best match if confidence is high enough
|
|
375
|
+
if (bestMatch.confidence >= 2) {
|
|
376
|
+
return `${project}\\${bestMatch.areaPath}`;
|
|
377
|
+
}
|
|
378
|
+
|
|
340
379
|
// Default area path
|
|
341
380
|
return project;
|
|
342
381
|
}
|
|
@@ -22,6 +22,11 @@ This is a **SpecWeave project** where specifications and documentation are the s
|
|
|
22
22
|
|
|
23
23
|
## Project Structure
|
|
24
24
|
|
|
25
|
+
**IMPORTANT**: This project uses {MONOREPO_OR_SINGLE} mode.
|
|
26
|
+
|
|
27
|
+
{#IF_SINGLE_PROJECT}
|
|
28
|
+
### Single Project Structure
|
|
29
|
+
|
|
25
30
|
```
|
|
26
31
|
.specweave/
|
|
27
32
|
├── increments/ # Feature increments (auto-numbered)
|
|
@@ -36,7 +41,8 @@ This is a **SpecWeave project** where specifications and documentation are the s
|
|
|
36
41
|
│ └── reports/ # Analysis, completion reports
|
|
37
42
|
├── docs/internal/
|
|
38
43
|
│ ├── strategy/ # Business specs (WHAT, WHY)
|
|
39
|
-
│ ├── specs/ # Feature specifications (
|
|
44
|
+
│ ├── specs/ # Feature specifications (living docs)
|
|
45
|
+
│ │ └── default/ # ✅ All specs in default project
|
|
40
46
|
│ ├── architecture/ # Technical design (HOW)
|
|
41
47
|
│ ├── delivery/ # Roadmap, CI/CD, guides
|
|
42
48
|
│ ├── operations/ # Runbooks, SLOs
|
|
@@ -55,6 +61,54 @@ plugins/ # Optional plugins (extended capabilities)
|
|
|
55
61
|
├── agents/ # Plugin-specific agents
|
|
56
62
|
└── commands/ # Plugin-specific commands
|
|
57
63
|
```
|
|
64
|
+
{#ENDIF}
|
|
65
|
+
|
|
66
|
+
{#IF_MULTI_PROJECT}
|
|
67
|
+
### Multi-Project Structure (v0.16.11+ Flattened)
|
|
68
|
+
|
|
69
|
+
**CRITICAL**: Specs are organized by project with FLATTENED structure (v0.16.11+).
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
.specweave/
|
|
73
|
+
├── docs/internal/
|
|
74
|
+
│ ├── strategy/ # Cross-project strategy
|
|
75
|
+
│ ├── specs/ # ✅ FLATTENED structure (v0.16.11+)
|
|
76
|
+
│ │ ├── backend/ # Backend project specs
|
|
77
|
+
│ │ │ ├── spec-001-api-auth.md
|
|
78
|
+
│ │ │ └── spec-002-data-layer.md
|
|
79
|
+
│ │ ├── frontend/ # Frontend project specs
|
|
80
|
+
│ │ │ ├── spec-001-user-dashboard.md
|
|
81
|
+
│ │ │ └── spec-002-dark-mode.md
|
|
82
|
+
│ │ ├── mobile/ # Mobile project specs (if applicable)
|
|
83
|
+
│ │ │ └── spec-001-push-notifications.md
|
|
84
|
+
│ │ └── _parent/ # Parent repo specs (multi-repo only)
|
|
85
|
+
│ │ └── spec-001-system-architecture.md
|
|
86
|
+
│ ├── architecture/ # System-wide technical design
|
|
87
|
+
│ ├── delivery/ # Cross-project delivery
|
|
88
|
+
│ ├── operations/ # Cross-project operations
|
|
89
|
+
│ └── governance/ # Cross-project governance
|
|
90
|
+
├── increments/
|
|
91
|
+
│ ├── 0001-backend-auth/ # Backend increment
|
|
92
|
+
│ ├── 0002-frontend-ui/ # Frontend increment
|
|
93
|
+
│ └── 0003-mobile-push/ # Mobile increment
|
|
94
|
+
└── ...
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Living Docs Path Format**:
|
|
98
|
+
- ✅ **CORRECT** (v0.16.11+): `.specweave/docs/internal/specs/{project-id}/spec-NNN-name.md`
|
|
99
|
+
- ❌ **OLD** (v0.8.0-v0.16.10): `.specweave/docs/internal/projects/{project-id}/specs/...` (DEPRECATED)
|
|
100
|
+
|
|
101
|
+
**Project Detection** (automatic):
|
|
102
|
+
- **From increment name**: `0001-backend-auth` → project: `backend`
|
|
103
|
+
- **From tech stack**: React/Next.js → `frontend`, ASP.NET/Node.js → `backend`
|
|
104
|
+
- **From config**: `multiProject.activeProject` in `.specweave/config.json`
|
|
105
|
+
- **Fallback**: Uses `default` project
|
|
106
|
+
|
|
107
|
+
**When creating living docs specs**:
|
|
108
|
+
1. Detect project from increment name or tech stack
|
|
109
|
+
2. Use flattened path: `specs/{project-id}/spec-NNN-name.md`
|
|
110
|
+
3. Never use old nested structure: `projects/{project-id}/specs/...`
|
|
111
|
+
{#ENDIF}
|
|
58
112
|
|
|
59
113
|
**CRITICAL**: Always read `context-manifest.yaml` first! Only load files listed there.
|
|
60
114
|
|
|
@@ -289,13 +289,19 @@ Config: Auto-detected from project files
|
|
|
289
289
|
|
|
290
290
|
## Project Structure
|
|
291
291
|
|
|
292
|
+
**IMPORTANT**: This project uses {MONOREPO_OR_SINGLE} mode.
|
|
293
|
+
|
|
294
|
+
{#IF_SINGLE_PROJECT}
|
|
295
|
+
### Single Project Structure
|
|
296
|
+
|
|
292
297
|
```
|
|
293
298
|
{PROJECT_NAME}/
|
|
294
299
|
├── .specweave/
|
|
295
300
|
│ ├── docs/ # Strategic documentation
|
|
296
301
|
│ │ ├── internal/
|
|
297
302
|
│ │ │ ├── strategy/ # Business specs (WHAT, WHY)
|
|
298
|
-
│ │ │ ├── specs/ # Feature specifications (
|
|
303
|
+
│ │ │ ├── specs/ # Feature specifications (living docs)
|
|
304
|
+
│ │ │ │ └── default/ # ✅ All specs in default project
|
|
299
305
|
│ │ │ ├── architecture/ # Technical design (HOW)
|
|
300
306
|
│ │ │ ├── delivery/ # Guides, roadmap, CI/CD
|
|
301
307
|
│ │ │ ├── operations/ # Runbooks, monitoring
|
|
@@ -319,6 +325,50 @@ Config: Auto-detected from project files
|
|
|
319
325
|
├── CLAUDE.md # This file
|
|
320
326
|
└── src/ # Your source code
|
|
321
327
|
```
|
|
328
|
+
{#ENDIF}
|
|
329
|
+
|
|
330
|
+
{#IF_MULTI_PROJECT}
|
|
331
|
+
### Multi-Project Structure (v0.16.11+ Flattened)
|
|
332
|
+
|
|
333
|
+
**CRITICAL**: Specs are organized by project with FLATTENED structure (v0.16.11+).
|
|
334
|
+
|
|
335
|
+
```
|
|
336
|
+
{PROJECT_NAME}/
|
|
337
|
+
├── .specweave/
|
|
338
|
+
│ ├── docs/internal/
|
|
339
|
+
│ │ ├── strategy/ # Cross-project strategy
|
|
340
|
+
│ │ ├── specs/ # ✅ FLATTENED structure (v0.16.11+)
|
|
341
|
+
│ │ │ ├── backend/ # Backend project specs
|
|
342
|
+
│ │ │ │ ├── spec-001-api-auth.md
|
|
343
|
+
│ │ │ │ └── spec-002-data-layer.md
|
|
344
|
+
│ │ │ ├── frontend/ # Frontend project specs
|
|
345
|
+
│ │ │ │ ├── spec-001-user-dashboard.md
|
|
346
|
+
│ │ │ │ └── spec-002-dark-mode.md
|
|
347
|
+
│ │ │ ├── mobile/ # Mobile project specs (if applicable)
|
|
348
|
+
│ │ │ │ └── spec-001-push-notifications.md
|
|
349
|
+
│ │ │ └── _parent/ # Parent repo specs (multi-repo only)
|
|
350
|
+
│ │ │ └── spec-001-system-architecture.md
|
|
351
|
+
│ │ ├── architecture/ # System-wide technical design
|
|
352
|
+
│ │ ├── delivery/ # Cross-project delivery
|
|
353
|
+
│ │ ├── operations/ # Cross-project operations
|
|
354
|
+
│ │ └── governance/ # Cross-project governance
|
|
355
|
+
│ ├── increments/
|
|
356
|
+
│ │ ├── 0001-backend-auth/ # Backend increment
|
|
357
|
+
│ │ ├── 0002-frontend-ui/ # Frontend increment
|
|
358
|
+
│ │ └── 0003-mobile-push/ # Mobile increment
|
|
359
|
+
│ └── ...
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
**Living Docs Path Format**:
|
|
363
|
+
- ✅ **CORRECT** (v0.16.11+): `.specweave/docs/internal/specs/{project-id}/spec-NNN-name.md`
|
|
364
|
+
- ❌ **OLD** (v0.8.0-v0.16.10): `.specweave/docs/internal/projects/{project-id}/specs/...` (DEPRECATED)
|
|
365
|
+
|
|
366
|
+
**Project Detection** (automatic):
|
|
367
|
+
- **From increment name**: `0001-backend-auth` → project: `backend`
|
|
368
|
+
- **From tech stack**: React/Next.js → `frontend`, ASP.NET/Node.js → `backend`
|
|
369
|
+
- **From config**: `multiProject.activeProject` in `.specweave/config.json`
|
|
370
|
+
- **Fallback**: Uses `default` project
|
|
371
|
+
{#ENDIF}
|
|
322
372
|
|
|
323
373
|
---
|
|
324
374
|
|