specweave 0.23.1 → 0.23.4
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/marketplace.json +0 -88
- package/CLAUDE.md +368 -0
- package/bin/fix-marketplace-errors.sh +8 -8
- package/dist/plugins/specweave/lib/utils/fs-native.d.ts +133 -0
- package/dist/plugins/specweave/lib/utils/fs-native.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/utils/fs-native.js +224 -0
- package/dist/plugins/specweave/lib/utils/fs-native.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.js +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.js +52 -20
- package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -1
- package/dist/src/cli/helpers/init/initial-increment-generator.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/initial-increment-generator.js +2 -1
- package/dist/src/cli/helpers/init/initial-increment-generator.js.map +1 -1
- package/dist/src/core/ac-test-validator-cli.d.ts +16 -0
- package/dist/src/core/ac-test-validator-cli.d.ts.map +1 -0
- package/dist/src/core/ac-test-validator-cli.js +118 -0
- package/dist/src/core/ac-test-validator-cli.js.map +1 -0
- package/dist/src/core/ac-test-validator.d.ts +111 -0
- package/dist/src/core/ac-test-validator.d.ts.map +1 -0
- package/dist/src/core/ac-test-validator.js +292 -0
- package/dist/src/core/ac-test-validator.js.map +1 -0
- package/dist/src/core/increment/desync-detector.d.ts +142 -0
- package/dist/src/core/increment/desync-detector.d.ts.map +1 -0
- package/dist/src/core/increment/desync-detector.js +270 -0
- package/dist/src/core/increment/desync-detector.js.map +1 -0
- package/dist/src/core/increment/metadata-manager.d.ts +8 -4
- package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
- package/dist/src/core/increment/metadata-manager.js +45 -21
- package/dist/src/core/increment/metadata-manager.js.map +1 -1
- package/dist/src/core/qa/qa-runner.js +9 -2
- package/dist/src/core/qa/qa-runner.js.map +1 -1
- package/dist/src/sync/sync-coordinator.d.ts +1 -1
- package/dist/src/sync/sync-coordinator.d.ts.map +1 -1
- package/dist/src/sync/sync-coordinator.js +40 -2
- package/dist/src/sync/sync-coordinator.js.map +1 -1
- package/dist/src/utils/fs-native.d.ts +133 -0
- package/dist/src/utils/fs-native.d.ts.map +1 -0
- package/dist/src/utils/fs-native.js +224 -0
- package/dist/src/utils/fs-native.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/.claude-plugin/plugin.json +22 -0
- package/plugins/specweave/agents/AGENTS-INDEX.md +216 -0
- package/plugins/specweave/agents/architect/AGENT.md +17 -0
- package/plugins/specweave/agents/code-standards-detective/AGENT.md +16 -0
- package/plugins/specweave/agents/docs-writer/AGENT.md +16 -0
- package/plugins/specweave/agents/increment-quality-judge-v2/AGENT.md +704 -0
- package/plugins/specweave/agents/infrastructure/AGENT.md +16 -0
- package/plugins/specweave/agents/performance/AGENT.md +16 -0
- package/plugins/specweave/agents/pm/AGENT.md +17 -0
- package/plugins/specweave/agents/qa-lead/AGENT.md +15 -0
- package/plugins/specweave/agents/reflective-reviewer/AGENT.md +16 -0
- package/plugins/specweave/agents/security/AGENT.md +16 -0
- package/plugins/specweave/agents/tdd-orchestrator/AGENT.md +16 -0
- package/plugins/specweave/agents/tech-lead/AGENT.md +16 -0
- package/plugins/specweave/agents/test-aware-planner/AGENT.md +16 -0
- package/plugins/specweave/agents/translator/AGENT.md +13 -0
- package/plugins/specweave/commands/specweave-done.md +14 -0
- package/plugins/specweave/commands/specweave-qa.md +11 -1
- package/plugins/specweave/commands/specweave-sync-status.md +356 -0
- package/plugins/specweave/commands/specweave-validate.md +10 -1
- package/plugins/specweave/hooks/post-metadata-change.sh +160 -0
- package/plugins/specweave/hooks/pre-task-completion.sh +196 -0
- package/plugins/specweave/lib/hooks/git-diff-analyzer.js +3 -3
- package/plugins/specweave/lib/hooks/git-diff-analyzer.ts +3 -3
- package/plugins/specweave/lib/hooks/invoke-translator-skill.js +3 -2
- package/plugins/specweave/lib/hooks/invoke-translator-skill.ts +3 -2
- package/plugins/specweave/lib/hooks/prepare-reflection-context.js +3 -3
- package/plugins/specweave/lib/hooks/prepare-reflection-context.ts +3 -3
- package/plugins/specweave/lib/hooks/reflection-config-loader.js +4 -4
- package/plugins/specweave/lib/hooks/reflection-config-loader.ts +4 -4
- package/plugins/specweave/lib/hooks/reflection-storage.js +9 -9
- package/plugins/specweave/lib/hooks/reflection-storage.ts +9 -9
- package/plugins/specweave/lib/hooks/sync-cache.js +9 -8
- package/plugins/specweave/lib/hooks/sync-living-docs.js +57 -6
- package/plugins/specweave/lib/hooks/sync-us-tasks.js +6 -6
- package/plugins/specweave/lib/hooks/translate-file.js +3 -2
- package/plugins/specweave/lib/hooks/translate-file.ts +3 -2
- package/plugins/specweave/lib/hooks/translate-living-docs.js +4 -3
- package/plugins/specweave/lib/hooks/translate-living-docs.ts +4 -3
- package/plugins/specweave/lib/utils/fs-native.js +182 -0
- package/plugins/specweave/lib/utils/fs-native.ts +283 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.d.ts +8 -4
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +45 -21
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -1
- package/plugins/specweave/skills/SKILLS-INDEX.md +26 -2
- package/plugins/specweave/skills/increment-planner/SKILL.md +2 -2
- package/plugins/specweave-ado/commands/specweave-ado-close-workitem.md +1 -1
- package/plugins/specweave-ado/commands/specweave-ado-create-workitem.md +1 -1
- package/plugins/specweave-ado/commands/specweave-ado-status.md +1 -1
- package/plugins/specweave-ado/commands/specweave-ado-sync.md +1 -1
- package/plugins/specweave-diagrams/agents/diagrams-architect/AGENT.md +1 -1
- package/plugins/specweave-diagrams/skills/diagrams-generator/SKILL.md +4 -4
- package/plugins/specweave-github/lib/github-client-v2.js +2 -1
- package/plugins/specweave-github/lib/github-client-v2.ts +1 -1
- package/plugins/specweave-github/lib/github-feature-sync.js +30 -17
- package/plugins/specweave-github/lib/github-feature-sync.ts +54 -24
- package/plugins/specweave-mobile/README.md +1 -1
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +72 -0
- package/plugins/specweave/skills/task-builder/README.md +0 -84
|
@@ -73,28 +73,6 @@
|
|
|
73
73
|
"email": "anton.abyzov@gmail.com"
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
|
-
{
|
|
77
|
-
"name": "specweave-figma",
|
|
78
|
-
"description": "Figma design system - MCP integration, design tokens, code generation",
|
|
79
|
-
"source": "./plugins/specweave-figma",
|
|
80
|
-
"category": "development",
|
|
81
|
-
"version": "1.0.0",
|
|
82
|
-
"author": {
|
|
83
|
-
"name": "Anton Abyzov",
|
|
84
|
-
"email": "anton.abyzov@gmail.com"
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
"name": "specweave-frontend",
|
|
89
|
-
"description": "Frontend development - React, Vue, Angular, Next.js, design systems",
|
|
90
|
-
"source": "./plugins/specweave-frontend",
|
|
91
|
-
"category": "development",
|
|
92
|
-
"version": "1.0.0",
|
|
93
|
-
"author": {
|
|
94
|
-
"name": "Anton Abyzov",
|
|
95
|
-
"email": "anton.abyzov@gmail.com"
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
76
|
{
|
|
99
77
|
"name": "specweave-backend",
|
|
100
78
|
"description": "Backend development - Node.js, Python, .NET, REST APIs",
|
|
@@ -128,28 +106,6 @@
|
|
|
128
106
|
"email": "anton.abyzov@gmail.com"
|
|
129
107
|
}
|
|
130
108
|
},
|
|
131
|
-
{
|
|
132
|
-
"name": "specweave-testing",
|
|
133
|
-
"description": "Test execution infrastructure - Playwright E2E, browser automation, visual regression",
|
|
134
|
-
"source": "./plugins/specweave-testing",
|
|
135
|
-
"category": "development",
|
|
136
|
-
"version": "1.0.0",
|
|
137
|
-
"author": {
|
|
138
|
-
"name": "Anton Abyzov",
|
|
139
|
-
"email": "anton.abyzov@gmail.com"
|
|
140
|
-
}
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
"name": "specweave-docs",
|
|
144
|
-
"description": "Documentation - Docusaurus generation, spec-driven workflows",
|
|
145
|
-
"source": "./plugins/specweave-docs",
|
|
146
|
-
"category": "productivity",
|
|
147
|
-
"version": "1.0.0",
|
|
148
|
-
"author": {
|
|
149
|
-
"name": "Anton Abyzov",
|
|
150
|
-
"email": "anton.abyzov@gmail.com"
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
109
|
{
|
|
154
110
|
"name": "specweave-docs-preview",
|
|
155
111
|
"description": "Interactive documentation preview - Launch Docusaurus dev server with hot reload, auto-generated sidebar, Mermaid diagrams. Build static sites for deployment.",
|
|
@@ -161,50 +117,6 @@
|
|
|
161
117
|
"email": "anton.abyzov@gmail.com"
|
|
162
118
|
}
|
|
163
119
|
},
|
|
164
|
-
{
|
|
165
|
-
"name": "specweave-tooling",
|
|
166
|
-
"description": "SpecWeave tooling - skill creation, skill routing",
|
|
167
|
-
"source": "./plugins/specweave-tooling",
|
|
168
|
-
"category": "development",
|
|
169
|
-
"version": "1.0.0",
|
|
170
|
-
"author": {
|
|
171
|
-
"name": "Anton Abyzov",
|
|
172
|
-
"email": "anton.abyzov@gmail.com"
|
|
173
|
-
}
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
"name": "specweave-alternatives",
|
|
177
|
-
"description": "Framework alternative experts - Compare SpecWeave with BMAD, spec-kit, openspec. Gap analysis and recommendations.",
|
|
178
|
-
"source": "./plugins/specweave-alternatives",
|
|
179
|
-
"category": "learning",
|
|
180
|
-
"version": "1.0.0",
|
|
181
|
-
"author": {
|
|
182
|
-
"name": "Anton Abyzov",
|
|
183
|
-
"email": "anton.abyzov@gmail.com"
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
"name": "specweave-ui",
|
|
188
|
-
"description": "UI components and design systems - Reusable component libraries",
|
|
189
|
-
"source": "./plugins/specweave-ui",
|
|
190
|
-
"category": "development",
|
|
191
|
-
"version": "1.0.0",
|
|
192
|
-
"author": {
|
|
193
|
-
"name": "Anton Abyzov",
|
|
194
|
-
"email": "anton.abyzov@gmail.com"
|
|
195
|
-
}
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
"name": "specweave-cost-optimizer",
|
|
199
|
-
"description": "Cost optimization - cloud platform comparison, cost breakdown",
|
|
200
|
-
"source": "./plugins/specweave-cost-optimizer",
|
|
201
|
-
"category": "productivity",
|
|
202
|
-
"version": "1.0.0",
|
|
203
|
-
"author": {
|
|
204
|
-
"name": "Anton Abyzov",
|
|
205
|
-
"email": "anton.abyzov@gmail.com"
|
|
206
|
-
}
|
|
207
|
-
},
|
|
208
120
|
{
|
|
209
121
|
"name": "specweave-diagrams",
|
|
210
122
|
"description": "Architecture diagrams - Mermaid, C4 Model, sequence, ER diagrams",
|
package/CLAUDE.md
CHANGED
|
@@ -314,6 +314,90 @@ npx tsx src/core/status-line-validator.ts
|
|
|
314
314
|
|
|
315
315
|
**Incident Reference**: 2025-11-20 - Status line showed 21/52 tasks when actually 26/52 were complete (10% desync). Root cause: Tasks marked complete without using TodoWrite, so hooks never fired. Added validation layer and tests to prevent future occurrences.
|
|
316
316
|
|
|
317
|
+
### 7b. GitHub Duplicate Prevention (CRITICAL!)
|
|
318
|
+
|
|
319
|
+
**CRITICAL**: External tool items (GitHub issues, JIRA tickets, ADO work items) MUST NEVER be duplicated.
|
|
320
|
+
|
|
321
|
+
**Rule**: ALWAYS use DuplicateDetector for GitHub issue creation.
|
|
322
|
+
|
|
323
|
+
**Why This Matters**:
|
|
324
|
+
- GitHub search has eventual consistency (2-5 second lag)
|
|
325
|
+
- Race conditions can create duplicates if sync runs multiple times quickly
|
|
326
|
+
- Manual search with `--limit 1` hides duplicates
|
|
327
|
+
|
|
328
|
+
**The ONLY Way to Create GitHub Issues**:
|
|
329
|
+
```typescript
|
|
330
|
+
import { DuplicateDetector } from './duplicate-detector.js';
|
|
331
|
+
|
|
332
|
+
// ✅ CORRECT: Use DuplicateDetector.createWithProtection()
|
|
333
|
+
const titlePattern = `[${featureId}][${userStory.id}]`; // e.g., "[FS-047][US-001]"
|
|
334
|
+
const result = await DuplicateDetector.createWithProtection({
|
|
335
|
+
title: issueContent.title,
|
|
336
|
+
body: issueContent.body,
|
|
337
|
+
titlePattern,
|
|
338
|
+
labels: issueContent.labels,
|
|
339
|
+
milestone: milestoneTitle,
|
|
340
|
+
repo: `${owner}/${repo}`
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
// Provides automatic:
|
|
344
|
+
// ✅ Phase 1 (Detection): Search for existing before create
|
|
345
|
+
// ✅ Phase 2 (Verification): Count-check after creation
|
|
346
|
+
// ✅ Phase 3 (Reflection): Auto-close duplicates, keep oldest
|
|
347
|
+
|
|
348
|
+
// ❌ WRONG: Manual gh issue create (no duplicate protection!)
|
|
349
|
+
execSync('gh issue create --title "..." --body "..."');
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**3-Phase Protection**:
|
|
353
|
+
1. **Detection** - Search GitHub for existing issues BEFORE creating
|
|
354
|
+
2. **Verification** - Count-check AFTER creation (handles eventual consistency)
|
|
355
|
+
3. **Reflection** - Auto-close duplicates if detected, keep oldest
|
|
356
|
+
|
|
357
|
+
**Search Limits** (CRITICAL!):
|
|
358
|
+
```typescript
|
|
359
|
+
// ❌ WRONG: --limit 1 hides duplicates!
|
|
360
|
+
gh issue list --search "[FS-047][US-001] in:title" --limit 1
|
|
361
|
+
// Returns ONLY 1 result even if 10 duplicates exist!
|
|
362
|
+
|
|
363
|
+
// ✅ CORRECT: --limit 50 detects duplicates
|
|
364
|
+
gh issue list --search "[FS-047][US-001] in:title" --limit 50
|
|
365
|
+
// Returns up to 50 results, enabling duplicate detection
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**Cleanup Existing Duplicates**:
|
|
369
|
+
```bash
|
|
370
|
+
# Preview what will be cleaned up:
|
|
371
|
+
bash scripts/cleanup-duplicate-github-issues.sh --dry-run
|
|
372
|
+
|
|
373
|
+
# Actually close duplicates (keeps oldest):
|
|
374
|
+
bash scripts/cleanup-duplicate-github-issues.sh
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
**Validation**:
|
|
378
|
+
```bash
|
|
379
|
+
# Check for duplicates:
|
|
380
|
+
gh issue list --json title,createdAt --limit 100 | \
|
|
381
|
+
jq -r '.[] | .title' | sort | uniq -d
|
|
382
|
+
|
|
383
|
+
# If output is empty → No duplicates! ✅
|
|
384
|
+
# If output shows titles → Duplicates exist, investigate!
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
**Why This Matters**:
|
|
388
|
+
- Incident 2025-11-20: 10+ duplicate User Story issues created
|
|
389
|
+
- Root Cause #1: Race condition (GitHub search eventual consistency lag)
|
|
390
|
+
- Root Cause #2: `--limit 1` bug (hid duplicates in search results)
|
|
391
|
+
- Root Cause #3: No post-create verification
|
|
392
|
+
- **Fix**: DuplicateDetector integration (github-feature-sync.ts:149-227)
|
|
393
|
+
|
|
394
|
+
**Protected Files**:
|
|
395
|
+
- `plugins/specweave-github/lib/github-feature-sync.ts` - Uses DuplicateDetector
|
|
396
|
+
- `plugins/specweave-github/lib/duplicate-detector.ts` - 3-phase protection
|
|
397
|
+
- `plugins/specweave-github/lib/github-client-v2.ts` - Fixed --limit 50
|
|
398
|
+
|
|
399
|
+
**Incident Reference**: 2025-11-20 - Duplicate GitHub issues for User Stories ([SP-US-006], [SP-US-007], etc.). Root cause: Race conditions + --limit 1 bug + missing DuplicateDetector integration. Fixed by implementing 3-phase protection. See `.specweave/increments/0047-us-task-linkage/reports/DUPLICATE-GITHUB-ISSUES-ROOT-CAUSE.md`.
|
|
400
|
+
|
|
317
401
|
### 8. NEVER Use `console.*` in Production Code
|
|
318
402
|
|
|
319
403
|
**Rule**: ALL `src/` code MUST use logger abstraction, NEVER `console.log/error/warn`.
|
|
@@ -662,6 +746,290 @@ const isArchived = archivedList.some(item => item === searchId);
|
|
|
662
746
|
|
|
663
747
|
**See Also**: `.specweave/increments/0047-us-task-linkage/reports/CRITICAL-ARCHIVING-BUGS-FIX.md`
|
|
664
748
|
|
|
749
|
+
### 14. Marketplace Plugin Completeness (CRITICAL!)
|
|
750
|
+
|
|
751
|
+
**NEVER add incomplete plugins to `.claude-plugin/marketplace.json`**
|
|
752
|
+
|
|
753
|
+
**Rule**: ONLY plugins with complete implementation (agents/, commands/, or lib/) may be listed in marketplace.json.
|
|
754
|
+
|
|
755
|
+
**Why This Matters**:
|
|
756
|
+
When users install `npm i -g specweave`, Claude Code loads ALL plugins listed in marketplace.json. Incomplete plugins (skeleton-only with just skills/) cause loading errors that confuse users and damage the framework's reputation.
|
|
757
|
+
|
|
758
|
+
**Incomplete Plugin Definition**:
|
|
759
|
+
A plugin is considered INCOMPLETE if it ONLY has:
|
|
760
|
+
- `.claude-plugin/` directory
|
|
761
|
+
- `skills/` directory
|
|
762
|
+
|
|
763
|
+
A plugin is COMPLETE if it has ANY of:
|
|
764
|
+
- `agents/` directory (specialized Claude Code agents)
|
|
765
|
+
- `commands/` directory (slash commands)
|
|
766
|
+
- `lib/` directory (shared utilities, TypeScript implementations)
|
|
767
|
+
|
|
768
|
+
**Validation Process** (MANDATORY before ANY marketplace.json changes):
|
|
769
|
+
|
|
770
|
+
```bash
|
|
771
|
+
# 1. Run validation script
|
|
772
|
+
bash scripts/validate-marketplace-plugins.sh
|
|
773
|
+
|
|
774
|
+
# Expected output: "✅ VALIDATION PASSED!"
|
|
775
|
+
# If FAILED: Remove incomplete plugins from marketplace.json
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
**Examples**:
|
|
779
|
+
|
|
780
|
+
```bash
|
|
781
|
+
# ✅ COMPLETE plugins (may be listed in marketplace.json):
|
|
782
|
+
plugins/specweave-github/
|
|
783
|
+
├── .claude-plugin/
|
|
784
|
+
├── agents/ ← Has agents
|
|
785
|
+
├── commands/ ← Has commands
|
|
786
|
+
├── lib/ ← Has lib
|
|
787
|
+
└── skills/
|
|
788
|
+
|
|
789
|
+
plugins/specweave-kafka/
|
|
790
|
+
├── .claude-plugin/
|
|
791
|
+
├── agents/ ← Has agents
|
|
792
|
+
├── lib/ ← Has lib
|
|
793
|
+
└── skills/
|
|
794
|
+
|
|
795
|
+
# ✗ INCOMPLETE plugins (MUST NOT be listed in marketplace.json):
|
|
796
|
+
plugins/specweave-cost-optimizer/
|
|
797
|
+
├── .claude-plugin/
|
|
798
|
+
└── skills/ ← ONLY skills!
|
|
799
|
+
|
|
800
|
+
plugins/specweave-figma/
|
|
801
|
+
├── .claude-plugin/
|
|
802
|
+
└── skills/ ← ONLY skills!
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
**Adding New Plugins**:
|
|
806
|
+
|
|
807
|
+
```bash
|
|
808
|
+
# 1. Create plugin with COMPLETE structure
|
|
809
|
+
mkdir -p plugins/specweave-newplugin/{.claude-plugin,agents,skills}
|
|
810
|
+
|
|
811
|
+
# 2. Implement at least ONE of: agents/, commands/, or lib/
|
|
812
|
+
# (Don't just create empty directories!)
|
|
813
|
+
|
|
814
|
+
# 3. Add to marketplace.json
|
|
815
|
+
vim .claude-plugin/marketplace.json
|
|
816
|
+
|
|
817
|
+
# 4. VALIDATE (this is CRITICAL!)
|
|
818
|
+
bash scripts/validate-marketplace-plugins.sh
|
|
819
|
+
|
|
820
|
+
# 5. Update bin/fix-marketplace-errors.sh
|
|
821
|
+
vim bin/fix-marketplace-errors.sh
|
|
822
|
+
# Add "specweave-newplugin" to plugins=(...) array
|
|
823
|
+
|
|
824
|
+
# 6. Commit
|
|
825
|
+
git add .claude-plugin/marketplace.json bin/fix-marketplace-errors.sh
|
|
826
|
+
git commit -m "feat: add specweave-newplugin to marketplace"
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
**Pre-Commit Hook** (TODO - add this):
|
|
830
|
+
```bash
|
|
831
|
+
# .git/hooks/pre-commit should run:
|
|
832
|
+
bash scripts/validate-marketplace-plugins.sh
|
|
833
|
+
# Block commit if validation fails
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
**Incident History**:
|
|
837
|
+
- **2025-11-20**: Global npm install caused 8 incomplete plugins to fail loading, generating confusing errors for users. Root cause: marketplace.json listed skeleton plugins that weren't ready for distribution.
|
|
838
|
+
|
|
839
|
+
**Prevention**:
|
|
840
|
+
1. Run `bash scripts/validate-marketplace-plugins.sh` before EVERY marketplace.json change
|
|
841
|
+
2. NEVER add plugins to marketplace.json until they have agents/, commands/, or lib/
|
|
842
|
+
3. Update bin/fix-marketplace-errors.sh whenever marketplace.json changes
|
|
843
|
+
4. Test global npm install (`npm pack && npm i -g ./specweave-*.tgz`) before releases
|
|
844
|
+
|
|
845
|
+
**See Also**:
|
|
846
|
+
- Validation script: `scripts/validate-marketplace-plugins.sh`
|
|
847
|
+
- Fix script: `bin/fix-marketplace-errors.sh`
|
|
848
|
+
|
|
849
|
+
### 15. Skills vs Agents: Understanding the Distinction (CRITICAL!)
|
|
850
|
+
|
|
851
|
+
**NEVER confuse skills with agents** - They are different components with different invocation methods.
|
|
852
|
+
|
|
853
|
+
**The Problem**:
|
|
854
|
+
Empty agent directories cause "Agent type not found" errors when someone tries to invoke them. This happened with `specweave:increment-quality-judge-v2` which existed as a skill but had an empty agent directory.
|
|
855
|
+
|
|
856
|
+
**Key Differences**:
|
|
857
|
+
|
|
858
|
+
| Aspect | Skills | Agents |
|
|
859
|
+
|--------|--------|--------|
|
|
860
|
+
| **Location** | `plugins/*/skills/name/SKILL.md` | `plugins/*/agents/name/AGENT.md` |
|
|
861
|
+
| **Invocation** | Skill tool or slash commands | Task tool with `subagent_type` |
|
|
862
|
+
| **Activation** | Automatic (based on keywords) | Explicit (you call them) |
|
|
863
|
+
| **Required File** | `SKILL.md` with YAML frontmatter | `AGENT.md` or agent config |
|
|
864
|
+
| **Purpose** | Expand context with knowledge | Execute multi-step tasks |
|
|
865
|
+
|
|
866
|
+
**Correct Invocation Examples**:
|
|
867
|
+
|
|
868
|
+
```typescript
|
|
869
|
+
// ✅ CORRECT: Invoking a skill
|
|
870
|
+
Skill({ skill: "increment-quality-judge-v2" });
|
|
871
|
+
// OR use slash command:
|
|
872
|
+
/specweave:qa 0047
|
|
873
|
+
|
|
874
|
+
// ✅ CORRECT: Invoking an agent
|
|
875
|
+
Task({
|
|
876
|
+
subagent_type: "specweave:qa-lead:qa-lead",
|
|
877
|
+
prompt: "Create test plan for increment 0047"
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
// ❌ WRONG: Trying to invoke skill as agent
|
|
881
|
+
Task({
|
|
882
|
+
subagent_type: "specweave:increment-quality-judge-v2", // ERROR!
|
|
883
|
+
prompt: "Quality assessment"
|
|
884
|
+
});
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
**Agent Naming Convention** (CRITICAL!):
|
|
888
|
+
|
|
889
|
+
Claude Code agents follow a strict naming pattern for `subagent_type`:
|
|
890
|
+
|
|
891
|
+
**Directory-based agents**: `{plugin-name}:{directory-name}:{name-from-yaml}`
|
|
892
|
+
|
|
893
|
+
Examples:
|
|
894
|
+
- Agent at `plugins/specweave/agents/qa-lead/AGENT.md` with `name: qa-lead`
|
|
895
|
+
→ Invoke as: `specweave:qa-lead:qa-lead`
|
|
896
|
+
- Agent at `plugins/specweave/agents/pm/AGENT.md` with `name: pm`
|
|
897
|
+
→ Invoke as: `specweave:pm:pm`
|
|
898
|
+
- Agent at `plugins/specweave/agents/architect/AGENT.md` with `name: architect`
|
|
899
|
+
→ Invoke as: `specweave:architect:architect`
|
|
900
|
+
|
|
901
|
+
**Why the "duplication"?**
|
|
902
|
+
The pattern is `{plugin}:{directory}:{yaml-name}`. When the directory name matches the YAML `name` field (best practice), it creates the appearance of duplication: `qa-lead:qa-lead`.
|
|
903
|
+
|
|
904
|
+
**File-based agents** (legacy pattern):
|
|
905
|
+
- Agent at `plugins/specweave/agents/code-reviewer.md`
|
|
906
|
+
→ Invoke as: `specweave:code-reviewer` (no duplication)
|
|
907
|
+
|
|
908
|
+
**How to find the correct agent type**:
|
|
909
|
+
```bash
|
|
910
|
+
# List all available agents
|
|
911
|
+
ls -la plugins/specweave/agents/
|
|
912
|
+
|
|
913
|
+
# Check YAML name field
|
|
914
|
+
head -5 plugins/specweave/agents/qa-lead/AGENT.md
|
|
915
|
+
# Output: name: qa-lead
|
|
916
|
+
|
|
917
|
+
# Construct agent type: specweave:qa-lead:qa-lead
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
**Common Mistakes**:
|
|
921
|
+
```typescript
|
|
922
|
+
// ❌ WRONG: Missing the directory/name duplication
|
|
923
|
+
Task({ subagent_type: "specweave:qa-lead", ... });
|
|
924
|
+
// Error: Agent type 'specweave:qa-lead' not found
|
|
925
|
+
|
|
926
|
+
// ✅ CORRECT: Full pattern with duplication
|
|
927
|
+
Task({ subagent_type: "specweave:qa-lead:qa-lead", ... });
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
**Directory Structure Requirements**:
|
|
931
|
+
|
|
932
|
+
```bash
|
|
933
|
+
# ✅ CORRECT: Skill with SKILL.md
|
|
934
|
+
plugins/specweave/skills/increment-quality-judge-v2/
|
|
935
|
+
└── SKILL.md (with YAML frontmatter)
|
|
936
|
+
|
|
937
|
+
# ✅ CORRECT: Agent with AGENT.md
|
|
938
|
+
plugins/specweave/agents/qa-lead/
|
|
939
|
+
└── AGENT.md
|
|
940
|
+
|
|
941
|
+
# ❌ WRONG: Empty agent directory
|
|
942
|
+
plugins/specweave/agents/increment-quality-judge-v2/
|
|
943
|
+
(empty - no AGENT.md!)
|
|
944
|
+
|
|
945
|
+
# ❌ WRONG: Skill missing SKILL.md
|
|
946
|
+
plugins/specweave/skills/my-skill/
|
|
947
|
+
└── some-file.txt (not SKILL.md!)
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
**SKILL.md Format** (MANDATORY):
|
|
951
|
+
```yaml
|
|
952
|
+
---
|
|
953
|
+
name: skill-name
|
|
954
|
+
description: What it does AND trigger keywords. Include all variations.
|
|
955
|
+
---
|
|
956
|
+
|
|
957
|
+
# Skill Content
|
|
958
|
+
|
|
959
|
+
Your skill documentation here...
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
**Validation** (MANDATORY before commits):
|
|
963
|
+
|
|
964
|
+
```bash
|
|
965
|
+
# Check for empty/invalid directories
|
|
966
|
+
bash scripts/validate-plugin-directories.sh
|
|
967
|
+
|
|
968
|
+
# Auto-fix empty directories
|
|
969
|
+
bash scripts/validate-plugin-directories.sh --fix
|
|
970
|
+
|
|
971
|
+
# This catches:
|
|
972
|
+
# - Empty agent/skill directories
|
|
973
|
+
# - Missing SKILL.md files
|
|
974
|
+
# - Missing YAML frontmatter
|
|
975
|
+
# - Invalid plugin structures
|
|
976
|
+
```
|
|
977
|
+
|
|
978
|
+
**Common Mistakes**:
|
|
979
|
+
|
|
980
|
+
1. **Creating empty agent directories during scaffolding**
|
|
981
|
+
```bash
|
|
982
|
+
# ❌ WRONG
|
|
983
|
+
mkdir -p plugins/specweave/agents/new-agent
|
|
984
|
+
git add . && git commit # Empty directory!
|
|
985
|
+
|
|
986
|
+
# ✅ CORRECT
|
|
987
|
+
mkdir -p plugins/specweave/agents/new-agent
|
|
988
|
+
echo "---" > plugins/specweave/agents/new-agent/AGENT.md
|
|
989
|
+
# ... add agent content ...
|
|
990
|
+
git add . && git commit
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
2. **Copying skill as agent without changing structure**
|
|
994
|
+
- Skills need `SKILL.md` with YAML
|
|
995
|
+
- Agents need `AGENT.md` or config
|
|
996
|
+
- Don't copy-paste between them!
|
|
997
|
+
|
|
998
|
+
3. **Using wrong invocation method**
|
|
999
|
+
- Check available skills: Skills list in context
|
|
1000
|
+
- Check available agents: Error message shows all agents
|
|
1001
|
+
- Skills → Skill tool or slash commands
|
|
1002
|
+
- Agents → Task tool
|
|
1003
|
+
|
|
1004
|
+
**When to Use Skills vs Agents**:
|
|
1005
|
+
|
|
1006
|
+
**Use Skills when**:
|
|
1007
|
+
- Providing domain knowledge (e.g., Kafka best practices)
|
|
1008
|
+
- Expanding Claude's context with project-specific info
|
|
1009
|
+
- Explaining concepts, patterns, frameworks
|
|
1010
|
+
- Want automatic activation based on keywords
|
|
1011
|
+
|
|
1012
|
+
**Use Agents when**:
|
|
1013
|
+
- Need multi-step task execution (e.g., generate docs)
|
|
1014
|
+
- Require specialized sub-agent capabilities
|
|
1015
|
+
- Building complex workflows with tools
|
|
1016
|
+
- Want explicit control over when they run
|
|
1017
|
+
|
|
1018
|
+
**Incident History**:
|
|
1019
|
+
- **2025-11-20**: `specweave:increment-quality-judge-v2` agent invocation failed because only skill existed. Empty agent directory caused "Agent type not found" error. Fixed by removing empty directory and documenting distinction.
|
|
1020
|
+
|
|
1021
|
+
**Prevention**:
|
|
1022
|
+
1. Run `bash scripts/validate-plugin-directories.sh` before commits
|
|
1023
|
+
2. Never create empty agent/skill directories
|
|
1024
|
+
3. Always include required files (SKILL.md, AGENT.md)
|
|
1025
|
+
4. Test invocation method matches component type
|
|
1026
|
+
5. Use pre-commit hook (blocks invalid structures)
|
|
1027
|
+
|
|
1028
|
+
**See Also**:
|
|
1029
|
+
- Validation script: `scripts/validate-plugin-directories.sh`
|
|
1030
|
+
- Skills index: `plugins/specweave/skills/SKILLS-INDEX.md`
|
|
1031
|
+
- Claude Code Skills docs: `~/CLAUDE.md` (Personal skills reference)
|
|
1032
|
+
|
|
665
1033
|
---
|
|
666
1034
|
|
|
667
1035
|
## Project Structure
|
|
@@ -63,6 +63,8 @@ else
|
|
|
63
63
|
fi
|
|
64
64
|
|
|
65
65
|
print_info "Step 6: Installing SpecWeave plugins..."
|
|
66
|
+
# IMPORTANT: Only list COMPLETE plugins (those with agents/, commands/, or lib/)
|
|
67
|
+
# NEVER add plugins that only have skills/ directory - they will fail to load!
|
|
66
68
|
plugins=(
|
|
67
69
|
"specweave"
|
|
68
70
|
"specweave-github"
|
|
@@ -70,19 +72,17 @@ plugins=(
|
|
|
70
72
|
"specweave-ado"
|
|
71
73
|
"specweave-kubernetes"
|
|
72
74
|
"specweave-infrastructure"
|
|
73
|
-
"specweave-figma"
|
|
74
|
-
"specweave-frontend"
|
|
75
75
|
"specweave-backend"
|
|
76
76
|
"specweave-payments"
|
|
77
77
|
"specweave-ml"
|
|
78
|
-
"specweave-testing"
|
|
79
|
-
"specweave-docs"
|
|
80
|
-
"specweave-tooling"
|
|
81
|
-
"specweave-alternatives"
|
|
82
|
-
"specweave-ui"
|
|
83
|
-
"specweave-cost-optimizer"
|
|
84
78
|
"specweave-diagrams"
|
|
85
79
|
"specweave-docs-preview"
|
|
80
|
+
"specweave-release"
|
|
81
|
+
"specweave-mobile"
|
|
82
|
+
"specweave-kafka"
|
|
83
|
+
"specweave-kafka-streams"
|
|
84
|
+
"specweave-confluent"
|
|
85
|
+
"specweave-n8n"
|
|
86
86
|
)
|
|
87
87
|
|
|
88
88
|
installed=0
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Node.js fs API Helpers
|
|
3
|
+
*
|
|
4
|
+
* Drop-in replacements for fs-extra methods using only Node.js stdlib.
|
|
5
|
+
* All methods use native Node.js 20+ APIs with no external dependencies.
|
|
6
|
+
*
|
|
7
|
+
* Migration from fs-extra:
|
|
8
|
+
* - import fs from 'fs-extra' → import * as fs from './utils/fs-native.js'
|
|
9
|
+
* - All fs-extra methods work as drop-in replacements
|
|
10
|
+
*
|
|
11
|
+
* Benefits:
|
|
12
|
+
* - Zero bundle overhead (no npm packages)
|
|
13
|
+
* - Works in marketplace (no node_modules needed)
|
|
14
|
+
* - Faster startup (native APIs)
|
|
15
|
+
* - Better debugging (native stack traces)
|
|
16
|
+
*/
|
|
17
|
+
import { promises as fsPromises, existsSync, mkdirSync, readFileSync, writeFileSync, statSync, readdirSync, rmSync, unlinkSync } from 'fs';
|
|
18
|
+
/**
|
|
19
|
+
* Ensures that a directory exists. If the directory does not exist, it is created.
|
|
20
|
+
* @param dirPath - The directory path to ensure
|
|
21
|
+
*/
|
|
22
|
+
export declare function ensureDir(dirPath: string): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Synchronous version of ensureDir
|
|
25
|
+
*/
|
|
26
|
+
export declare function ensureDirSync(dirPath: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Alias for ensureDirSync (fs-extra compatibility)
|
|
29
|
+
*/
|
|
30
|
+
export declare function mkdirpSync(dirPath: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Check if a path exists
|
|
33
|
+
* @param filePath - The path to check
|
|
34
|
+
*/
|
|
35
|
+
export declare function pathExists(filePath: string): Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* Synchronous version of pathExists
|
|
38
|
+
*/
|
|
39
|
+
export { existsSync };
|
|
40
|
+
/**
|
|
41
|
+
* Read a JSON file and parse it
|
|
42
|
+
* @param filePath - The JSON file path
|
|
43
|
+
*/
|
|
44
|
+
export declare function readJson(filePath: string): Promise<any>;
|
|
45
|
+
/**
|
|
46
|
+
* Synchronous version of readJson
|
|
47
|
+
*/
|
|
48
|
+
export declare function readJsonSync(filePath: string): any;
|
|
49
|
+
/**
|
|
50
|
+
* Write a JSON file with formatting
|
|
51
|
+
* @param filePath - The JSON file path
|
|
52
|
+
* @param data - The data to write
|
|
53
|
+
* @param options - Options (spaces for indentation)
|
|
54
|
+
*/
|
|
55
|
+
export declare function writeJson(filePath: string, data: any, options?: {
|
|
56
|
+
spaces?: number;
|
|
57
|
+
}): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Synchronous version of writeJson
|
|
60
|
+
*/
|
|
61
|
+
export declare function writeJsonSync(filePath: string, data: any, options?: {
|
|
62
|
+
spaces?: number;
|
|
63
|
+
}): void;
|
|
64
|
+
/**
|
|
65
|
+
* Remove a file or directory (recursively)
|
|
66
|
+
* @param targetPath - The path to remove
|
|
67
|
+
*/
|
|
68
|
+
export declare function remove(targetPath: string): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Synchronous version of remove
|
|
71
|
+
*/
|
|
72
|
+
export declare function removeSync(targetPath: string): void;
|
|
73
|
+
/**
|
|
74
|
+
* Copy a file or directory
|
|
75
|
+
* @param src - Source path
|
|
76
|
+
* @param dest - Destination path
|
|
77
|
+
* @param options - Copy options
|
|
78
|
+
*/
|
|
79
|
+
export declare function copy(src: string, dest: string, options?: {
|
|
80
|
+
overwrite?: boolean;
|
|
81
|
+
filter?: (src: string) => boolean;
|
|
82
|
+
}): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Synchronous version of copy
|
|
85
|
+
*/
|
|
86
|
+
export declare function copySync(src: string, dest: string, options?: {
|
|
87
|
+
overwrite?: boolean;
|
|
88
|
+
filter?: (src: string) => boolean;
|
|
89
|
+
}): void;
|
|
90
|
+
/**
|
|
91
|
+
* Ensure a file exists (create if it doesn't)
|
|
92
|
+
* @param filePath - The file path
|
|
93
|
+
*/
|
|
94
|
+
export declare function ensureFile(filePath: string): Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* Synchronous version of ensureFile
|
|
97
|
+
*/
|
|
98
|
+
export declare function ensureFileSync(filePath: string): void;
|
|
99
|
+
export declare const readFile: typeof fsPromises.readFile, writeFile: typeof fsPromises.writeFile, appendFile: typeof fsPromises.appendFile, stat: typeof fsPromises.stat, readdir: typeof fsPromises.readdir, access: typeof fsPromises.access, unlink: typeof fsPromises.unlink, rmdir: typeof fsPromises.rmdir, rename: typeof fsPromises.rename, chmod: typeof fsPromises.chmod;
|
|
100
|
+
export { readFileSync, writeFileSync, statSync, readdirSync, unlinkSync, mkdirSync, rmSync, };
|
|
101
|
+
declare const _default: {
|
|
102
|
+
ensureDir: typeof ensureDir;
|
|
103
|
+
pathExists: typeof pathExists;
|
|
104
|
+
readJson: typeof readJson;
|
|
105
|
+
writeJson: typeof writeJson;
|
|
106
|
+
remove: typeof remove;
|
|
107
|
+
copy: typeof copy;
|
|
108
|
+
ensureFile: typeof ensureFile;
|
|
109
|
+
readFile: typeof fsPromises.readFile;
|
|
110
|
+
writeFile: typeof fsPromises.writeFile;
|
|
111
|
+
appendFile: typeof fsPromises.appendFile;
|
|
112
|
+
stat: typeof fsPromises.stat;
|
|
113
|
+
readdir: typeof fsPromises.readdir;
|
|
114
|
+
access: typeof fsPromises.access;
|
|
115
|
+
unlink: typeof fsPromises.unlink;
|
|
116
|
+
ensureDirSync: typeof ensureDirSync;
|
|
117
|
+
mkdirpSync: typeof mkdirpSync;
|
|
118
|
+
existsSync: typeof existsSync;
|
|
119
|
+
readJsonSync: typeof readJsonSync;
|
|
120
|
+
writeJsonSync: typeof writeJsonSync;
|
|
121
|
+
removeSync: typeof removeSync;
|
|
122
|
+
copySync: typeof copySync;
|
|
123
|
+
ensureFileSync: typeof ensureFileSync;
|
|
124
|
+
readFileSync: typeof readFileSync;
|
|
125
|
+
writeFileSync: typeof writeFileSync;
|
|
126
|
+
statSync: import("fs").StatSyncFn;
|
|
127
|
+
readdirSync: typeof readdirSync;
|
|
128
|
+
unlinkSync: typeof unlinkSync;
|
|
129
|
+
mkdirSync: typeof mkdirSync;
|
|
130
|
+
rmSync: typeof rmSync;
|
|
131
|
+
};
|
|
132
|
+
export default _default;
|
|
133
|
+
//# sourceMappingURL=fs-native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-native.d.ts","sourceRoot":"","sources":["../../../../../plugins/specweave/lib/utils/fs-native.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAgB,MAAM,IAAI,CAAC;AAIzJ;;;GAGG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI9D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAInD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEhD;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEnE;AAED;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAG7D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAGlD;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,GAAG,EACT,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5B,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,GAAG,EACT,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5B,IAAI,CAIN;AAED;;;GAGG;AACH,wBAAsB,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI9D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAInD;AAED;;;;;GAKG;AACH,wBAAsB,IAAI,CACxB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;CAAE,GACnE,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;CAAE,GACnE,IAAI,CA4BN;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKhE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAKrD;AAGD,eAAO,MACL,QAAQ,8BACR,SAAS,+BACT,UAAU,gCACV,IAAI,0BACJ,OAAO,6BACP,MAAM,4BACN,MAAM,4BACN,KAAK,2BACL,MAAM,4BACN,KAAK,yBACO,CAAC;AAGf,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,WAAW,EACX,UAAU,EACV,SAAS,EACT,MAAM,GACP,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGF,wBAiCE"}
|