specweave 0.3.13 → 0.4.1
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 +506 -17
- package/README.md +100 -58
- package/bin/install-all.sh +9 -2
- package/bin/install-hooks.sh +57 -0
- package/bin/specweave.js +16 -0
- package/dist/adapters/adapter-base.d.ts +21 -0
- package/dist/adapters/adapter-base.d.ts.map +1 -1
- package/dist/adapters/adapter-base.js +28 -0
- package/dist/adapters/adapter-base.js.map +1 -1
- package/dist/adapters/adapter-interface.d.ts +41 -0
- package/dist/adapters/adapter-interface.d.ts.map +1 -1
- package/dist/adapters/claude/adapter.d.ts +36 -0
- package/dist/adapters/claude/adapter.d.ts.map +1 -1
- package/dist/adapters/claude/adapter.js +135 -0
- package/dist/adapters/claude/adapter.js.map +1 -1
- package/dist/adapters/copilot/adapter.d.ts +25 -0
- package/dist/adapters/copilot/adapter.d.ts.map +1 -1
- package/dist/adapters/copilot/adapter.js +112 -0
- package/dist/adapters/copilot/adapter.js.map +1 -1
- package/dist/adapters/cursor/adapter.d.ts +36 -0
- package/dist/adapters/cursor/adapter.d.ts.map +1 -1
- package/dist/adapters/cursor/adapter.js +140 -0
- package/dist/adapters/cursor/adapter.js.map +1 -1
- package/dist/adapters/generic/adapter.d.ts +25 -0
- package/dist/adapters/generic/adapter.d.ts.map +1 -1
- package/dist/adapters/generic/adapter.js +111 -0
- package/dist/adapters/generic/adapter.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +103 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/plugin.d.ts +37 -0
- package/dist/cli/commands/plugin.d.ts.map +1 -0
- package/dist/cli/commands/plugin.js +296 -0
- package/dist/cli/commands/plugin.js.map +1 -0
- package/dist/core/agent-model-manager.d.ts +52 -0
- package/dist/core/agent-model-manager.d.ts.map +1 -0
- package/dist/core/agent-model-manager.js +120 -0
- package/dist/core/agent-model-manager.js.map +1 -0
- package/dist/core/cost-tracker.d.ts +108 -0
- package/dist/core/cost-tracker.d.ts.map +1 -0
- package/dist/core/cost-tracker.js +281 -0
- package/dist/core/cost-tracker.js.map +1 -0
- package/dist/core/model-selector.d.ts +57 -0
- package/dist/core/model-selector.d.ts.map +1 -0
- package/dist/core/model-selector.js +115 -0
- package/dist/core/model-selector.js.map +1 -0
- package/dist/core/phase-detector.d.ts +62 -0
- package/dist/core/phase-detector.d.ts.map +1 -0
- package/dist/core/phase-detector.js +229 -0
- package/dist/core/phase-detector.js.map +1 -0
- package/dist/core/plugin-detector.d.ts +96 -0
- package/dist/core/plugin-detector.d.ts.map +1 -0
- package/dist/core/plugin-detector.js +349 -0
- package/dist/core/plugin-detector.js.map +1 -0
- package/dist/core/plugin-loader.d.ts +111 -0
- package/dist/core/plugin-loader.d.ts.map +1 -0
- package/dist/core/plugin-loader.js +319 -0
- package/dist/core/plugin-loader.js.map +1 -0
- package/dist/core/plugin-manager.d.ts +144 -0
- package/dist/core/plugin-manager.d.ts.map +1 -0
- package/dist/core/plugin-manager.js +393 -0
- package/dist/core/plugin-manager.js.map +1 -0
- package/dist/core/schemas/plugin-manifest.schema.json +253 -0
- package/dist/core/types/plugin.d.ts +252 -0
- package/dist/core/types/plugin.d.ts.map +1 -0
- package/dist/core/types/plugin.js +48 -0
- package/dist/core/types/plugin.js.map +1 -0
- package/dist/integrations/jira/jira-mapper.d.ts +2 -2
- package/dist/integrations/jira/jira-mapper.js +2 -2
- package/dist/types/cost-tracking.d.ts +43 -0
- package/dist/types/cost-tracking.d.ts.map +1 -0
- package/dist/types/cost-tracking.js +8 -0
- package/dist/types/cost-tracking.js.map +1 -0
- package/dist/types/model-selection.d.ts +53 -0
- package/dist/types/model-selection.d.ts.map +1 -0
- package/dist/types/model-selection.js +12 -0
- package/dist/types/model-selection.js.map +1 -0
- package/dist/utils/cost-reporter.d.ts +58 -0
- package/dist/utils/cost-reporter.d.ts.map +1 -0
- package/dist/utils/cost-reporter.js +224 -0
- package/dist/utils/cost-reporter.js.map +1 -0
- package/dist/utils/pricing-constants.d.ts +70 -0
- package/dist/utils/pricing-constants.d.ts.map +1 -0
- package/dist/utils/pricing-constants.js +71 -0
- package/dist/utils/pricing-constants.js.map +1 -0
- package/package.json +13 -9
- package/src/adapters/adapter-base.ts +33 -0
- package/src/adapters/adapter-interface.ts +46 -0
- package/src/adapters/claude/adapter.ts +164 -0
- package/src/adapters/copilot/adapter.ts +138 -0
- package/src/adapters/cursor/adapter.ts +170 -0
- package/src/adapters/generic/adapter.ts +137 -0
- package/src/agents/architect/AGENT.md +3 -0
- package/src/agents/code-reviewer.md +156 -0
- package/src/agents/data-scientist/AGENT.md +181 -0
- package/src/agents/database-optimizer/AGENT.md +147 -0
- package/src/agents/devops/AGENT.md +3 -0
- package/src/agents/diagrams-architect/AGENT.md +3 -0
- package/src/agents/docs-writer/AGENT.md +3 -0
- package/src/agents/kubernetes-architect/AGENT.md +142 -0
- package/src/agents/ml-engineer/AGENT.md +150 -0
- package/src/agents/mlops-engineer/AGENT.md +201 -0
- package/src/agents/network-engineer/AGENT.md +149 -0
- package/src/agents/observability-engineer/AGENT.md +213 -0
- package/src/agents/payment-integration/AGENT.md +35 -0
- package/src/agents/performance/AGENT.md +3 -0
- package/src/agents/performance-engineer/AGENT.md +153 -0
- package/src/agents/pm/AGENT.md +3 -0
- package/src/agents/qa-lead/AGENT.md +3 -0
- package/src/agents/security/AGENT.md +3 -0
- package/src/agents/sre/AGENT.md +3 -0
- package/src/agents/tdd-orchestrator/AGENT.md +169 -0
- package/src/agents/tech-lead/AGENT.md +3 -0
- package/src/commands/specweave.costs.md +261 -0
- package/src/commands/specweave.increment.md +48 -4
- package/src/commands/specweave.ml-pipeline.md +292 -0
- package/src/commands/specweave.monitor-setup.md +501 -0
- package/src/commands/specweave.slo-implement.md +1055 -0
- package/src/commands/specweave.sync-github.md +1 -1
- package/src/commands/specweave.tdd-cycle.md +199 -0
- package/src/commands/specweave.tdd-green.md +842 -0
- package/src/commands/specweave.tdd-red.md +135 -0
- package/src/commands/specweave.tdd-refactor.md +165 -0
- package/src/hooks/post-increment-plugin-detect.sh +142 -0
- package/src/hooks/post-task-completion.sh +53 -11
- package/src/hooks/pre-task-plugin-detect.sh +96 -0
- package/src/skills/SKILLS-INDEX.md +18 -10
- package/src/skills/billing-automation/SKILL.md +559 -0
- package/src/skills/distributed-tracing/SKILL.md +438 -0
- package/src/skills/e2e-playwright/README.md +1 -1
- package/src/skills/e2e-playwright/package.json +1 -1
- package/src/skills/gitops-workflow/SKILL.md +285 -0
- package/src/skills/gitops-workflow/references/argocd-setup.md +134 -0
- package/src/skills/gitops-workflow/references/sync-policies.md +131 -0
- package/src/skills/grafana-dashboards/SKILL.md +369 -0
- package/src/skills/helm-chart-scaffolding/SKILL.md +544 -0
- package/src/skills/helm-chart-scaffolding/assets/Chart.yaml.template +42 -0
- package/src/skills/helm-chart-scaffolding/assets/values.yaml.template +185 -0
- package/src/skills/helm-chart-scaffolding/references/chart-structure.md +500 -0
- package/src/skills/helm-chart-scaffolding/scripts/validate-chart.sh +244 -0
- package/src/skills/k8s-manifest-generator/SKILL.md +511 -0
- package/src/skills/k8s-manifest-generator/assets/configmap-template.yaml +296 -0
- package/src/skills/k8s-manifest-generator/assets/deployment-template.yaml +203 -0
- package/src/skills/k8s-manifest-generator/assets/service-template.yaml +171 -0
- package/src/skills/k8s-manifest-generator/references/deployment-spec.md +753 -0
- package/src/skills/k8s-manifest-generator/references/service-spec.md +724 -0
- package/src/skills/k8s-security-policies/SKILL.md +334 -0
- package/src/skills/k8s-security-policies/assets/network-policy-template.yaml +177 -0
- package/src/skills/k8s-security-policies/references/rbac-patterns.md +187 -0
- package/src/skills/ml-pipeline-workflow/SKILL.md +245 -0
- package/src/skills/paypal-integration/SKILL.md +467 -0
- package/src/skills/pci-compliance/SKILL.md +466 -0
- package/src/skills/prometheus-configuration/SKILL.md +392 -0
- package/src/skills/slo-implementation/SKILL.md +329 -0
- package/src/skills/stripe-integration/SKILL.md +442 -0
- package/src/skills/tdd-workflow/SKILL.md +378 -0
- package/src/templates/README.md.template +1 -1
- package/src/skills/bmad-method-expert/SKILL.md +0 -626
- package/src/skills/bmad-method-expert/scripts/analyze-project.js +0 -318
- package/src/skills/bmad-method-expert/scripts/check-setup.js +0 -208
- package/src/skills/bmad-method-expert/scripts/generate-template.js +0 -1149
- package/src/skills/bmad-method-expert/scripts/validate-documents.js +0 -340
- package/src/skills/context-optimizer/SKILL.md +0 -588
- package/src/skills/figma-designer/SKILL.md +0 -149
- package/src/skills/figma-implementer/SKILL.md +0 -148
- package/src/skills/figma-mcp-connector/SKILL.md +0 -136
- package/src/skills/figma-to-code/SKILL.md +0 -128
- package/src/skills/spec-kit-expert/SKILL.md +0 -1010
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Write comprehensive failing tests following TDD red phase principles.
|
|
2
|
+
|
|
3
|
+
[Extended thinking: Generates failing tests that properly define expected behavior using test-automator agent.]
|
|
4
|
+
|
|
5
|
+
## Role
|
|
6
|
+
|
|
7
|
+
Generate failing tests using Task tool with subagent_type="unit-testing::test-automator".
|
|
8
|
+
|
|
9
|
+
## Prompt Template
|
|
10
|
+
|
|
11
|
+
"Generate comprehensive FAILING tests for: $ARGUMENTS
|
|
12
|
+
|
|
13
|
+
## Core Requirements
|
|
14
|
+
|
|
15
|
+
1. **Test Structure**
|
|
16
|
+
- Framework-appropriate setup (Jest/pytest/JUnit/Go/RSpec)
|
|
17
|
+
- Arrange-Act-Assert pattern
|
|
18
|
+
- should_X_when_Y naming convention
|
|
19
|
+
- Isolated fixtures with no interdependencies
|
|
20
|
+
|
|
21
|
+
2. **Behavior Coverage**
|
|
22
|
+
- Happy path scenarios
|
|
23
|
+
- Edge cases (empty, null, boundary values)
|
|
24
|
+
- Error handling and exceptions
|
|
25
|
+
- Concurrent access (if applicable)
|
|
26
|
+
|
|
27
|
+
3. **Failure Verification**
|
|
28
|
+
- Tests MUST fail when run
|
|
29
|
+
- Failures for RIGHT reasons (not syntax/import errors)
|
|
30
|
+
- Meaningful diagnostic error messages
|
|
31
|
+
- No cascading failures
|
|
32
|
+
|
|
33
|
+
4. **Test Categories**
|
|
34
|
+
- Unit: Isolated component behavior
|
|
35
|
+
- Integration: Component interaction
|
|
36
|
+
- Contract: API/interface contracts
|
|
37
|
+
- Property: Mathematical invariants
|
|
38
|
+
|
|
39
|
+
## Framework Patterns
|
|
40
|
+
|
|
41
|
+
**JavaScript/TypeScript (Jest/Vitest)**
|
|
42
|
+
- Mock dependencies with `vi.fn()` or `jest.fn()`
|
|
43
|
+
- Use `@testing-library` for React components
|
|
44
|
+
- Property tests with `fast-check`
|
|
45
|
+
|
|
46
|
+
**Python (pytest)**
|
|
47
|
+
- Fixtures with appropriate scopes
|
|
48
|
+
- Parametrize for multiple test cases
|
|
49
|
+
- Hypothesis for property-based tests
|
|
50
|
+
|
|
51
|
+
**Go**
|
|
52
|
+
- Table-driven tests with subtests
|
|
53
|
+
- `t.Parallel()` for parallel execution
|
|
54
|
+
- Use `testify/assert` for cleaner assertions
|
|
55
|
+
|
|
56
|
+
**Ruby (RSpec)**
|
|
57
|
+
- `let` for lazy loading, `let!` for eager
|
|
58
|
+
- Contexts for different scenarios
|
|
59
|
+
- Shared examples for common behavior
|
|
60
|
+
|
|
61
|
+
## Quality Checklist
|
|
62
|
+
|
|
63
|
+
- Readable test names documenting intent
|
|
64
|
+
- One behavior per test
|
|
65
|
+
- No implementation leakage
|
|
66
|
+
- Meaningful test data (not 'foo'/'bar')
|
|
67
|
+
- Tests serve as living documentation
|
|
68
|
+
|
|
69
|
+
## Anti-Patterns to Avoid
|
|
70
|
+
|
|
71
|
+
- Tests passing immediately
|
|
72
|
+
- Testing implementation vs behavior
|
|
73
|
+
- Complex setup code
|
|
74
|
+
- Multiple responsibilities per test
|
|
75
|
+
- Brittle tests tied to specifics
|
|
76
|
+
|
|
77
|
+
## Edge Case Categories
|
|
78
|
+
|
|
79
|
+
- **Null/Empty**: undefined, null, empty string/array/object
|
|
80
|
+
- **Boundaries**: min/max values, single element, capacity limits
|
|
81
|
+
- **Special Cases**: Unicode, whitespace, special characters
|
|
82
|
+
- **State**: Invalid transitions, concurrent modifications
|
|
83
|
+
- **Errors**: Network failures, timeouts, permissions
|
|
84
|
+
|
|
85
|
+
## Output Requirements
|
|
86
|
+
|
|
87
|
+
- Complete test files with imports
|
|
88
|
+
- Documentation of test purpose
|
|
89
|
+
- Commands to run and verify failures
|
|
90
|
+
- Metrics: test count, coverage areas
|
|
91
|
+
- Next steps for green phase"
|
|
92
|
+
|
|
93
|
+
## Validation
|
|
94
|
+
|
|
95
|
+
After generation:
|
|
96
|
+
1. Run tests - confirm they fail
|
|
97
|
+
2. Verify helpful failure messages
|
|
98
|
+
3. Check test independence
|
|
99
|
+
4. Ensure comprehensive coverage
|
|
100
|
+
|
|
101
|
+
## Example (Minimal)
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// auth.service.test.ts
|
|
105
|
+
describe('AuthService', () => {
|
|
106
|
+
let authService: AuthService;
|
|
107
|
+
let mockUserRepo: jest.Mocked<UserRepository>;
|
|
108
|
+
|
|
109
|
+
beforeEach(() => {
|
|
110
|
+
mockUserRepo = { findByEmail: jest.fn() } as any;
|
|
111
|
+
authService = new AuthService(mockUserRepo);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should_return_token_when_valid_credentials', async () => {
|
|
115
|
+
const user = { id: '1', email: 'test@example.com', passwordHash: 'hashed' };
|
|
116
|
+
mockUserRepo.findByEmail.mockResolvedValue(user);
|
|
117
|
+
|
|
118
|
+
const result = await authService.authenticate('test@example.com', 'pass');
|
|
119
|
+
|
|
120
|
+
expect(result.success).toBe(true);
|
|
121
|
+
expect(result.token).toBeDefined();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should_fail_when_user_not_found', async () => {
|
|
125
|
+
mockUserRepo.findByEmail.mockResolvedValue(null);
|
|
126
|
+
|
|
127
|
+
const result = await authService.authenticate('none@example.com', 'pass');
|
|
128
|
+
|
|
129
|
+
expect(result.success).toBe(false);
|
|
130
|
+
expect(result.error).toBe('INVALID_CREDENTIALS');
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Test requirements: $ARGUMENTS
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
Refactor code with confidence using comprehensive test safety net:
|
|
2
|
+
|
|
3
|
+
[Extended thinking: This tool uses the tdd-orchestrator agent (opus model) for sophisticated refactoring while maintaining all tests green. It applies design patterns, improves code quality, and optimizes performance with the safety of comprehensive test coverage.]
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
Use Task tool with subagent_type="tdd-orchestrator" to perform safe refactoring.
|
|
8
|
+
|
|
9
|
+
Prompt: "Refactor this code while keeping all tests green: $ARGUMENTS. Apply TDD refactor phase:
|
|
10
|
+
|
|
11
|
+
## Core Process
|
|
12
|
+
|
|
13
|
+
**1. Pre-Assessment**
|
|
14
|
+
- Run tests to establish green baseline
|
|
15
|
+
- Analyze code smells and test coverage
|
|
16
|
+
- Document current performance metrics
|
|
17
|
+
- Create incremental refactoring plan
|
|
18
|
+
|
|
19
|
+
**2. Code Smell Detection**
|
|
20
|
+
- Duplicated code → Extract methods/classes
|
|
21
|
+
- Long methods → Decompose into focused functions
|
|
22
|
+
- Large classes → Split responsibilities
|
|
23
|
+
- Long parameter lists → Parameter objects
|
|
24
|
+
- Feature Envy → Move methods to appropriate classes
|
|
25
|
+
- Primitive Obsession → Value objects
|
|
26
|
+
- Switch statements → Polymorphism
|
|
27
|
+
- Dead code → Remove
|
|
28
|
+
|
|
29
|
+
**3. Design Patterns**
|
|
30
|
+
- Apply Creational (Factory, Builder, Singleton)
|
|
31
|
+
- Apply Structural (Adapter, Facade, Decorator)
|
|
32
|
+
- Apply Behavioral (Strategy, Observer, Command)
|
|
33
|
+
- Apply Domain (Repository, Service, Value Objects)
|
|
34
|
+
- Use patterns only where they add clear value
|
|
35
|
+
|
|
36
|
+
**4. SOLID Principles**
|
|
37
|
+
- Single Responsibility: One reason to change
|
|
38
|
+
- Open/Closed: Open for extension, closed for modification
|
|
39
|
+
- Liskov Substitution: Subtypes substitutable
|
|
40
|
+
- Interface Segregation: Small, focused interfaces
|
|
41
|
+
- Dependency Inversion: Depend on abstractions
|
|
42
|
+
|
|
43
|
+
**5. Refactoring Techniques**
|
|
44
|
+
- Extract Method/Variable/Interface
|
|
45
|
+
- Inline unnecessary indirection
|
|
46
|
+
- Rename for clarity
|
|
47
|
+
- Move Method/Field to appropriate classes
|
|
48
|
+
- Replace Magic Numbers with constants
|
|
49
|
+
- Encapsulate fields
|
|
50
|
+
- Replace Conditional with Polymorphism
|
|
51
|
+
- Introduce Null Object
|
|
52
|
+
|
|
53
|
+
**6. Performance Optimization**
|
|
54
|
+
- Profile to identify bottlenecks
|
|
55
|
+
- Optimize algorithms and data structures
|
|
56
|
+
- Implement caching where beneficial
|
|
57
|
+
- Reduce database queries (N+1 elimination)
|
|
58
|
+
- Lazy loading and pagination
|
|
59
|
+
- Always measure before and after
|
|
60
|
+
|
|
61
|
+
**7. Incremental Steps**
|
|
62
|
+
- Make small, atomic changes
|
|
63
|
+
- Run tests after each modification
|
|
64
|
+
- Commit after each successful refactoring
|
|
65
|
+
- Keep refactoring separate from behavior changes
|
|
66
|
+
- Use scaffolding when needed
|
|
67
|
+
|
|
68
|
+
**8. Architecture Evolution**
|
|
69
|
+
- Layer separation and dependency management
|
|
70
|
+
- Module boundaries and interface definition
|
|
71
|
+
- Event-driven patterns for decoupling
|
|
72
|
+
- Database access pattern optimization
|
|
73
|
+
|
|
74
|
+
**9. Safety Verification**
|
|
75
|
+
- Run full test suite after each change
|
|
76
|
+
- Performance regression testing
|
|
77
|
+
- Mutation testing for test effectiveness
|
|
78
|
+
- Rollback plan for major changes
|
|
79
|
+
|
|
80
|
+
**10. Advanced Patterns**
|
|
81
|
+
- Strangler Fig: Gradual legacy replacement
|
|
82
|
+
- Branch by Abstraction: Large-scale changes
|
|
83
|
+
- Parallel Change: Expand-contract pattern
|
|
84
|
+
- Mikado Method: Dependency graph navigation
|
|
85
|
+
|
|
86
|
+
## Output Requirements
|
|
87
|
+
|
|
88
|
+
- Refactored code with improvements applied
|
|
89
|
+
- Test results (all green)
|
|
90
|
+
- Before/after metrics comparison
|
|
91
|
+
- Applied refactoring techniques list
|
|
92
|
+
- Performance improvement measurements
|
|
93
|
+
- Remaining technical debt assessment
|
|
94
|
+
|
|
95
|
+
## Safety Checklist
|
|
96
|
+
|
|
97
|
+
Before committing:
|
|
98
|
+
- ✓ All tests pass (100% green)
|
|
99
|
+
- ✓ No functionality regression
|
|
100
|
+
- ✓ Performance metrics acceptable
|
|
101
|
+
- ✓ Code coverage maintained/improved
|
|
102
|
+
- ✓ Documentation updated
|
|
103
|
+
|
|
104
|
+
## Recovery Protocol
|
|
105
|
+
|
|
106
|
+
If tests fail:
|
|
107
|
+
- Immediately revert last change
|
|
108
|
+
- Identify breaking refactoring
|
|
109
|
+
- Apply smaller incremental changes
|
|
110
|
+
- Use version control for safe experimentation
|
|
111
|
+
|
|
112
|
+
## Example: Extract Method Pattern
|
|
113
|
+
|
|
114
|
+
**Before:**
|
|
115
|
+
```typescript
|
|
116
|
+
class OrderProcessor {
|
|
117
|
+
processOrder(order: Order): ProcessResult {
|
|
118
|
+
// Validation
|
|
119
|
+
if (!order.customerId || order.items.length === 0) {
|
|
120
|
+
return { success: false, error: "Invalid order" };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Calculate totals
|
|
124
|
+
let subtotal = 0;
|
|
125
|
+
for (const item of order.items) {
|
|
126
|
+
subtotal += item.price * item.quantity;
|
|
127
|
+
}
|
|
128
|
+
let total = subtotal + (subtotal * 0.08) + (subtotal > 100 ? 0 : 15);
|
|
129
|
+
|
|
130
|
+
// Process payment...
|
|
131
|
+
// Update inventory...
|
|
132
|
+
// Send confirmation...
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**After:**
|
|
138
|
+
```typescript
|
|
139
|
+
class OrderProcessor {
|
|
140
|
+
async processOrder(order: Order): Promise<ProcessResult> {
|
|
141
|
+
const validation = this.validateOrder(order);
|
|
142
|
+
if (!validation.isValid) return ProcessResult.failure(validation.error);
|
|
143
|
+
|
|
144
|
+
const orderTotal = OrderTotal.calculate(order);
|
|
145
|
+
const inventoryCheck = await this.inventoryService.checkAvailability(order.items);
|
|
146
|
+
if (!inventoryCheck.available) return ProcessResult.failure(inventoryCheck.reason);
|
|
147
|
+
|
|
148
|
+
await this.paymentService.processPayment(order.paymentMethod, orderTotal.total);
|
|
149
|
+
await this.inventoryService.reserveItems(order.items);
|
|
150
|
+
await this.notificationService.sendOrderConfirmation(order, orderTotal);
|
|
151
|
+
|
|
152
|
+
return ProcessResult.success(order.id, orderTotal.total);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private validateOrder(order: Order): ValidationResult {
|
|
156
|
+
if (!order.customerId) return ValidationResult.invalid("Customer ID required");
|
|
157
|
+
if (order.items.length === 0) return ValidationResult.invalid("Order must contain items");
|
|
158
|
+
return ValidationResult.valid();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Applied:** Extract Method, Value Objects, Dependency Injection, Async patterns
|
|
164
|
+
|
|
165
|
+
Code to refactor: $ARGUMENTS"
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Post-Increment Plugin Detection Hook (T-021)
|
|
5
|
+
#
|
|
6
|
+
# Runs AFTER increment completion to suggest plugins based on git diff
|
|
7
|
+
# This is Phase 4 of the 4-phase plugin detection system
|
|
8
|
+
#
|
|
9
|
+
# Trigger: After `/specweave.done` completes an increment
|
|
10
|
+
# Output: Plugin suggestions for NEXT increment
|
|
11
|
+
#
|
|
12
|
+
|
|
13
|
+
# Exit on error
|
|
14
|
+
set -e
|
|
15
|
+
|
|
16
|
+
# Get project root (assumes hook runs from project directory)
|
|
17
|
+
PROJECT_ROOT=$(pwd)
|
|
18
|
+
|
|
19
|
+
# Colors for output
|
|
20
|
+
GREEN='\033[0;32m'
|
|
21
|
+
YELLOW='\033[1;33m'
|
|
22
|
+
CYAN='\033[0;36m'
|
|
23
|
+
GRAY='\033[0;37m'
|
|
24
|
+
MAGENTA='\033[0;35m'
|
|
25
|
+
NC='\033[0m' # No Color
|
|
26
|
+
|
|
27
|
+
# Check if SpecWeave is installed
|
|
28
|
+
if ! command -v specweave &> /dev/null; then
|
|
29
|
+
# Silent exit if SpecWeave not installed (development mode)
|
|
30
|
+
exit 0
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Check if git repository exists
|
|
34
|
+
if [ ! -d ".git" ]; then
|
|
35
|
+
# Not a git repo, skip detection
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Get completed increment number (passed as argument)
|
|
40
|
+
INCREMENT_NUM="$1"
|
|
41
|
+
|
|
42
|
+
if [ -z "$INCREMENT_NUM" ]; then
|
|
43
|
+
# No increment number provided, skip
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# Get git diff since last increment tag (or HEAD if no tags)
|
|
48
|
+
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "HEAD~10")
|
|
49
|
+
GIT_DIFF=$(git diff --name-only "$LAST_TAG"..HEAD 2>/dev/null || echo "")
|
|
50
|
+
|
|
51
|
+
if [ -z "$GIT_DIFF" ]; then
|
|
52
|
+
# No changes detected, skip
|
|
53
|
+
exit 0
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Also check package.json changes for new dependencies
|
|
57
|
+
PACKAGE_JSON_CHANGED=false
|
|
58
|
+
if echo "$GIT_DIFF" | grep -q "package.json"; then
|
|
59
|
+
PACKAGE_JSON_CHANGED=true
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Keyword-based plugin detection from file changes
|
|
63
|
+
declare -A PLUGIN_PATTERNS=(
|
|
64
|
+
["specweave-github"]=".github/|github-"
|
|
65
|
+
["specweave-kubernetes"]="kubernetes/|k8s/|helm/|\.yaml$"
|
|
66
|
+
["specweave-frontend-stack"]="components/|pages/|app/|\.tsx$|\.jsx$"
|
|
67
|
+
["specweave-backend-stack"]="api/|server/|routes/|controllers/"
|
|
68
|
+
["specweave-ml-ops"]="models/|training/|\.ipynb$|\.h5$|\.pkl$"
|
|
69
|
+
["specweave-payment-processing"]="payments/|billing/|stripe"
|
|
70
|
+
["specweave-figma"]="\.figma|design/|mockups/"
|
|
71
|
+
["specweave-observability"]="prometheus/|grafana/|monitoring/"
|
|
72
|
+
["specweave-diagrams"]="diagrams/|\.mmd$|architecture/"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Dependency-based detection (if package.json changed)
|
|
76
|
+
declare -A DEPENDENCY_PLUGINS=(
|
|
77
|
+
["specweave-frontend-stack"]="react|vue|angular|next"
|
|
78
|
+
["specweave-backend-stack"]="express|fastapi|django|nestjs"
|
|
79
|
+
["specweave-payment-processing"]="stripe|paypal"
|
|
80
|
+
["specweave-ml-ops"]="tensorflow|pytorch|scikit-learn"
|
|
81
|
+
["specweave-observability"]="prometheus-client|@opentelemetry"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Detect plugins based on file patterns
|
|
85
|
+
SUGGESTED_PLUGINS=()
|
|
86
|
+
|
|
87
|
+
# Check file patterns
|
|
88
|
+
for plugin in "${!PLUGIN_PATTERNS[@]}"; do
|
|
89
|
+
pattern="${PLUGIN_PATTERNS[$plugin]}"
|
|
90
|
+
|
|
91
|
+
if echo "$GIT_DIFF" | grep -qi -E "$pattern"; then
|
|
92
|
+
# Check if plugin is already enabled
|
|
93
|
+
if ! specweave plugin list --enabled 2>/dev/null | grep -q "$plugin"; then
|
|
94
|
+
if [[ ! " ${SUGGESTED_PLUGINS[@]} " =~ " ${plugin} " ]]; then
|
|
95
|
+
SUGGESTED_PLUGINS+=("$plugin")
|
|
96
|
+
fi
|
|
97
|
+
fi
|
|
98
|
+
fi
|
|
99
|
+
done
|
|
100
|
+
|
|
101
|
+
# Check package.json dependencies if it changed
|
|
102
|
+
if [ "$PACKAGE_JSON_CHANGED" = true ] && [ -f "package.json" ]; then
|
|
103
|
+
DEPENDENCIES=$(cat package.json | grep -A 100 '"dependencies"' | grep -A 100 '"devDependencies"' || echo "")
|
|
104
|
+
|
|
105
|
+
for plugin in "${!DEPENDENCY_PLUGINS[@]}"; do
|
|
106
|
+
keywords="${DEPENDENCY_PLUGINS[$plugin]}"
|
|
107
|
+
|
|
108
|
+
if echo "$DEPENDENCIES" | grep -qi -E "$keywords"; then
|
|
109
|
+
if ! specweave plugin list --enabled 2>/dev/null | grep -q "$plugin"; then
|
|
110
|
+
if [[ ! " ${SUGGESTED_PLUGINS[@]} " =~ " ${plugin} " ]]; then
|
|
111
|
+
SUGGESTED_PLUGINS+=("$plugin")
|
|
112
|
+
fi
|
|
113
|
+
fi
|
|
114
|
+
fi
|
|
115
|
+
done
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
# Output suggestions if any found
|
|
119
|
+
if [ ${#SUGGESTED_PLUGINS[@]} -gt 0 ]; then
|
|
120
|
+
echo ""
|
|
121
|
+
echo -e "${MAGENTA}══════════════════════════════════════════════════════${NC}"
|
|
122
|
+
echo -e "${CYAN}💡 Plugin Suggestions for Next Increment${NC}"
|
|
123
|
+
echo -e "${MAGENTA}══════════════════════════════════════════════════════${NC}"
|
|
124
|
+
echo ""
|
|
125
|
+
echo -e "${GRAY}Increment ${INCREMENT_NUM} introduced changes that suggest:${NC}"
|
|
126
|
+
echo ""
|
|
127
|
+
|
|
128
|
+
for plugin in "${SUGGESTED_PLUGINS[@]}"; do
|
|
129
|
+
echo -e " ✨ ${GREEN}${plugin}${NC}"
|
|
130
|
+
done
|
|
131
|
+
|
|
132
|
+
echo ""
|
|
133
|
+
echo -e "${YELLOW}Consider enabling these plugins for your next increment:${NC}"
|
|
134
|
+
echo -e "${CYAN} specweave plugin enable <name>${NC}"
|
|
135
|
+
echo ""
|
|
136
|
+
echo -e "${GRAY}Plugins will auto-activate skills and agents for better support${NC}"
|
|
137
|
+
echo -e "${MAGENTA}══════════════════════════════════════════════════════${NC}"
|
|
138
|
+
echo ""
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
# Always exit successfully (non-blocking)
|
|
142
|
+
exit 0
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
# Runs automatically after ANY task is marked complete via TodoWrite
|
|
5
5
|
#
|
|
6
6
|
# Actions:
|
|
7
|
-
# 1.
|
|
8
|
-
# 2.
|
|
9
|
-
# 3.
|
|
7
|
+
# 1. Check if ALL tasks are completed (parse stdin JSON)
|
|
8
|
+
# 2. Play completion sound ONLY if all tasks done
|
|
9
|
+
# 3. Output JSON systemMessage reminding to update docs
|
|
10
|
+
# 4. Log completion
|
|
10
11
|
#
|
|
11
12
|
# DEBOUNCING: Prevents rapid duplicate fires (Claude Code calls hooks twice)
|
|
12
13
|
|
|
@@ -42,16 +43,43 @@ fi
|
|
|
42
43
|
# Save current timestamp
|
|
43
44
|
echo "$CURRENT_TIME" > "$LAST_FIRE_FILE"
|
|
44
45
|
|
|
46
|
+
# Read stdin to temporary file
|
|
47
|
+
STDIN_DATA=$(mktemp)
|
|
48
|
+
cat > "$STDIN_DATA"
|
|
49
|
+
|
|
45
50
|
# DEBUG: Log hook invocation
|
|
46
51
|
echo "[$(date)] Hook invoked! PWD=$PWD Args=$*" >> .specweave/logs/hooks-debug.log 2>/dev/null || true
|
|
47
52
|
echo "[$(date)] Hook stdin:" >> .specweave/logs/hooks-debug.log 2>/dev/null || true
|
|
48
|
-
cat >> .specweave/logs/hooks-debug.log 2>/dev/null || true
|
|
53
|
+
cat "$STDIN_DATA" >> .specweave/logs/hooks-debug.log 2>/dev/null || true
|
|
54
|
+
|
|
55
|
+
# Parse JSON to check if ALL tasks are completed
|
|
56
|
+
# Extract todos array and check for any non-completed tasks
|
|
57
|
+
ALL_COMPLETED=false
|
|
58
|
+
|
|
59
|
+
if command -v jq >/dev/null 2>&1; then
|
|
60
|
+
# Use jq if available (more reliable)
|
|
61
|
+
PENDING_COUNT=$(jq -r '.tool_input.todos // [] | map(select(.status != "completed")) | length' "$STDIN_DATA" 2>/dev/null || echo "1")
|
|
62
|
+
|
|
63
|
+
if [ "$PENDING_COUNT" = "0" ]; then
|
|
64
|
+
ALL_COMPLETED=true
|
|
65
|
+
fi
|
|
66
|
+
else
|
|
67
|
+
# Fallback: Simple grep check (less reliable but works without jq)
|
|
68
|
+
if grep -q '"status":"pending"\|"status":"in_progress"' "$STDIN_DATA" 2>/dev/null; then
|
|
69
|
+
ALL_COMPLETED=false
|
|
70
|
+
else
|
|
71
|
+
# No pending/in_progress found - likely all completed
|
|
72
|
+
ALL_COMPLETED=true
|
|
73
|
+
fi
|
|
74
|
+
fi
|
|
49
75
|
|
|
50
|
-
#
|
|
76
|
+
# Clean up temp file
|
|
77
|
+
rm -f "$STDIN_DATA"
|
|
78
|
+
|
|
79
|
+
# 1. Play notification sound ONLY if ALL tasks are completed
|
|
51
80
|
play_sound() {
|
|
52
81
|
case "$(uname -s)" in
|
|
53
82
|
Darwin)
|
|
54
|
-
# Play synchronously (remove &)
|
|
55
83
|
afplay /System/Library/Sounds/Glass.aiff 2>/dev/null || true
|
|
56
84
|
;;
|
|
57
85
|
Linux)
|
|
@@ -64,16 +92,30 @@ play_sound() {
|
|
|
64
92
|
esac
|
|
65
93
|
}
|
|
66
94
|
|
|
67
|
-
# Play sound
|
|
68
|
-
|
|
95
|
+
# Play sound ONLY if all tasks completed
|
|
96
|
+
if [ "$ALL_COMPLETED" = "true" ]; then
|
|
97
|
+
echo "[$(date)] 🎉 ALL TASKS COMPLETED - Playing sound!" >> .specweave/logs/hooks-debug.log 2>/dev/null || true
|
|
98
|
+
play_sound
|
|
99
|
+
else
|
|
100
|
+
echo "[$(date)] Task completed, but more tasks remain (no sound)" >> .specweave/logs/hooks-debug.log 2>/dev/null || true
|
|
101
|
+
fi
|
|
69
102
|
|
|
70
103
|
# 2. Log completion
|
|
71
|
-
echo "[$(date)] Task completed" >> .specweave/logs/tasks.log 2>/dev/null || true
|
|
104
|
+
echo "[$(date)] Task completed (All done: $ALL_COMPLETED)" >> .specweave/logs/tasks.log 2>/dev/null || true
|
|
72
105
|
|
|
73
106
|
# 3. Output JSON to instruct Claude (systemMessage is shown to user)
|
|
74
|
-
|
|
107
|
+
if [ "$ALL_COMPLETED" = "true" ]; then
|
|
108
|
+
cat <<EOF
|
|
75
109
|
{
|
|
76
110
|
"continue": true,
|
|
77
|
-
"systemMessage": "
|
|
111
|
+
"systemMessage": "🎉 ALL TASKS COMPLETED! Remember to update documentation with inline edits to CLAUDE.md and README.md as needed."
|
|
78
112
|
}
|
|
79
113
|
EOF
|
|
114
|
+
else
|
|
115
|
+
cat <<EOF
|
|
116
|
+
{
|
|
117
|
+
"continue": true,
|
|
118
|
+
"systemMessage": "✅ Task completed. More tasks remaining - keep going!"
|
|
119
|
+
}
|
|
120
|
+
EOF
|
|
121
|
+
fi
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Pre-Task Plugin Detection Hook (T-020)
|
|
5
|
+
#
|
|
6
|
+
# Runs BEFORE task execution to suggest plugins based on task description
|
|
7
|
+
# This is Phase 3 of the 4-phase plugin detection system
|
|
8
|
+
#
|
|
9
|
+
# Trigger: Before executing any task via `/specweave.do`
|
|
10
|
+
# Output: Non-blocking plugin suggestions
|
|
11
|
+
#
|
|
12
|
+
|
|
13
|
+
# Exit on error
|
|
14
|
+
set -e
|
|
15
|
+
|
|
16
|
+
# Get project root (assumes hook runs from project directory)
|
|
17
|
+
PROJECT_ROOT=$(pwd)
|
|
18
|
+
|
|
19
|
+
# Colors for output
|
|
20
|
+
GREEN='\033[0;32m'
|
|
21
|
+
YELLOW='\033[1;33m'
|
|
22
|
+
CYAN='\033[0;36m'
|
|
23
|
+
GRAY='\033[0;37m'
|
|
24
|
+
NC='\033[0m' # No Color
|
|
25
|
+
|
|
26
|
+
# Check if SpecWeave is installed
|
|
27
|
+
if ! command -v specweave &> /dev/null; then
|
|
28
|
+
# Silent exit if SpecWeave not installed (development mode)
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Get current task being executed (passed as argument)
|
|
33
|
+
TASK_FILE="$1"
|
|
34
|
+
|
|
35
|
+
if [ -z "$TASK_FILE" ] || [ ! -f "$TASK_FILE" ]; then
|
|
36
|
+
# No task file provided, skip detection
|
|
37
|
+
exit 0
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Extract task description
|
|
41
|
+
TASK_DESCRIPTION=$(grep -A 5 "^### T-[0-9]" "$TASK_FILE" | head -1 || echo "")
|
|
42
|
+
|
|
43
|
+
if [ -z "$TASK_DESCRIPTION" ]; then
|
|
44
|
+
# No description found, skip
|
|
45
|
+
exit 0
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Keyword-based plugin detection
|
|
49
|
+
declare -A PLUGIN_KEYWORDS=(
|
|
50
|
+
["specweave-github"]="github|gh|issue|pull request|pr"
|
|
51
|
+
["specweave-kubernetes"]="kubernetes|k8s|kubectl|helm|pod|deployment"
|
|
52
|
+
["specweave-frontend-stack"]="react|vue|angular|nextjs|frontend|ui|component"
|
|
53
|
+
["specweave-backend-stack"]="express|fastapi|django|flask|nestjs|backend|api|server"
|
|
54
|
+
["specweave-ml-ops"]="tensorflow|pytorch|sklearn|ml|machine learning|model|training"
|
|
55
|
+
["specweave-payment-processing"]="stripe|paypal|payment|billing|subscription"
|
|
56
|
+
["specweave-figma"]="figma|design|mockup|prototype"
|
|
57
|
+
["specweave-jira"]="jira|atlassian|ticket"
|
|
58
|
+
["specweave-observability"]="prometheus|grafana|datadog|monitoring|metrics|tracing"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Detect plugins based on keywords
|
|
62
|
+
SUGGESTED_PLUGINS=()
|
|
63
|
+
|
|
64
|
+
for plugin in "${!PLUGIN_KEYWORDS[@]}"; do
|
|
65
|
+
keywords="${PLUGIN_KEYWORDS[$plugin]}"
|
|
66
|
+
|
|
67
|
+
# Check if any keyword matches (case-insensitive)
|
|
68
|
+
if echo "$TASK_DESCRIPTION" | grep -qi -E "$keywords"; then
|
|
69
|
+
# Check if plugin is already enabled
|
|
70
|
+
if ! specweave plugin list --enabled 2>/dev/null | grep -q "$plugin"; then
|
|
71
|
+
SUGGESTED_PLUGINS+=("$plugin")
|
|
72
|
+
fi
|
|
73
|
+
fi
|
|
74
|
+
done
|
|
75
|
+
|
|
76
|
+
# Output suggestions if any found
|
|
77
|
+
if [ ${#SUGGESTED_PLUGINS[@]} -gt 0 ]; then
|
|
78
|
+
echo ""
|
|
79
|
+
echo -e "${CYAN}💡 Plugin Detection${NC}"
|
|
80
|
+
echo ""
|
|
81
|
+
echo -e "${GRAY}Task mentions: ${TASK_DESCRIPTION}${NC}"
|
|
82
|
+
echo ""
|
|
83
|
+
echo -e "${YELLOW}Suggested plugins:${NC}"
|
|
84
|
+
|
|
85
|
+
for plugin in "${SUGGESTED_PLUGINS[@]}"; do
|
|
86
|
+
echo -e " • ${GREEN}${plugin}${NC}"
|
|
87
|
+
done
|
|
88
|
+
|
|
89
|
+
echo ""
|
|
90
|
+
echo -e "${GRAY}This task might benefit from these plugins.${NC}"
|
|
91
|
+
echo -e "${GRAY}Run: ${CYAN}specweave plugin enable <name>${GRAY} to install${NC}"
|
|
92
|
+
echo ""
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# Always exit successfully (non-blocking)
|
|
96
|
+
exit 0
|