@su-record/vibe 2.8.23 → 2.8.25
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/commands/vibe.figma.md +2 -2
- package/dist/cli/commands/config.d.ts +17 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +207 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/index.d.ts +2 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +2 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/info.d.ts.map +1 -1
- package/dist/cli/commands/info.js +2 -0
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +78 -54
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/stats.d.ts +13 -0
- package/dist/cli/commands/stats.d.ts.map +1 -0
- package/dist/cli/commands/stats.js +280 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +33 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/postinstall/constants.d.ts.map +1 -1
- package/dist/cli/postinstall/constants.js +1 -0
- package/dist/cli/postinstall/constants.js.map +1 -1
- package/dist/cli/setup/GlobalInstaller.d.ts.map +1 -1
- package/dist/cli/setup/GlobalInstaller.js +7 -7
- package/dist/cli/setup/GlobalInstaller.js.map +1 -1
- package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
- package/dist/cli/setup/ProjectSetup.js +18 -12
- package/dist/cli/setup/ProjectSetup.js.map +1 -1
- package/dist/infra/lib/ContextCompressor.d.ts.map +1 -1
- package/dist/infra/lib/ContextCompressor.js +10 -4
- package/dist/infra/lib/ContextCompressor.js.map +1 -1
- package/dist/infra/lib/ProjectCache.d.ts +2 -2
- package/dist/infra/lib/ProjectCache.d.ts.map +1 -1
- package/dist/infra/lib/ProjectCache.js +4 -3
- package/dist/infra/lib/ProjectCache.js.map +1 -1
- package/dist/infra/lib/utils.d.ts +24 -0
- package/dist/infra/lib/utils.d.ts.map +1 -1
- package/dist/infra/lib/utils.js +41 -0
- package/dist/infra/lib/utils.js.map +1 -1
- package/dist/infra/orchestrator/SmartRouter.d.ts +3 -0
- package/dist/infra/orchestrator/SmartRouter.d.ts.map +1 -1
- package/dist/infra/orchestrator/SmartRouter.js +11 -1
- package/dist/infra/orchestrator/SmartRouter.js.map +1 -1
- package/dist/infra/orchestrator/SmartRouter.test.d.ts +5 -0
- package/dist/infra/orchestrator/SmartRouter.test.d.ts.map +1 -0
- package/dist/infra/orchestrator/SmartRouter.test.js +457 -0
- package/dist/infra/orchestrator/SmartRouter.test.js.map +1 -0
- package/dist/tools/convention/analyzeComplexity.d.ts.map +1 -1
- package/dist/tools/convention/analyzeComplexity.js +18 -10
- package/dist/tools/convention/analyzeComplexity.js.map +1 -1
- package/dist/tools/convention/checkCouplingCohesion.d.ts.map +1 -1
- package/dist/tools/convention/checkCouplingCohesion.js +14 -6
- package/dist/tools/convention/checkCouplingCohesion.js.map +1 -1
- package/dist/tools/semantic/analyzeDependencyGraph.d.ts.map +1 -1
- package/dist/tools/semantic/analyzeDependencyGraph.js +1 -1
- package/dist/tools/semantic/analyzeDependencyGraph.js.map +1 -1
- package/dist/tools/semantic/findReferences.d.ts.map +1 -1
- package/dist/tools/semantic/findReferences.js +13 -13
- package/dist/tools/semantic/findReferences.js.map +1 -1
- package/dist/tools/semantic/findSymbol.d.ts.map +1 -1
- package/dist/tools/semantic/findSymbol.js +12 -13
- package/dist/tools/semantic/findSymbol.js.map +1 -1
- package/dist/tools/semantic/lsp.d.ts.map +1 -1
- package/dist/tools/semantic/lsp.js +22 -14
- package/dist/tools/semantic/lsp.js.map +1 -1
- package/hooks/hooks.json +29 -0
- package/hooks/scripts/__tests__/keyword-detector.test.js +199 -0
- package/hooks/scripts/__tests__/pre-tool-guard.test.js +286 -0
- package/hooks/scripts/__tests__/sentinel-guard.test.js +210 -0
- package/hooks/scripts/auto-commit.js +65 -0
- package/hooks/scripts/auto-format.js +64 -0
- package/hooks/scripts/auto-test.js +81 -0
- package/hooks/scripts/code-check.js +139 -0
- package/hooks/scripts/command-log.js +32 -0
- package/hooks/scripts/context-save.js +60 -6
- package/hooks/scripts/hud-status.js +32 -2
- package/hooks/scripts/llm-orchestrate.js +95 -17
- package/hooks/scripts/pr-test-gate.js +52 -0
- package/package.json +1 -1
- package/skills/agents-md/rubrics/what-to-keep.md +49 -0
- package/skills/agents-md/templates/agents-md.md +36 -0
- package/skills/arch-guard/agents/detector.md +48 -0
- package/skills/arch-guard/agents/reporter.md +48 -0
- package/skills/arch-guard/agents/rule-generator.md +49 -0
- package/skills/arch-guard/agents/violation-checker.md +51 -0
- package/skills/arch-guard/frameworks/clean-architecture.md +108 -0
- package/skills/arch-guard/frameworks/solid.md +102 -0
- package/skills/arch-guard/scripts/check-boundaries.js +90 -0
- package/skills/arch-guard/templates/arch-rules.json +47 -0
- package/skills/arch-guard/templates/violation-report.md +53 -0
- package/skills/brand-assets/rubrics/asset-checklist.md +98 -0
- package/skills/brand-assets/templates/brand-guide.md +161 -0
- package/skills/capability-loop/agents/capability-designer.md +61 -0
- package/skills/capability-loop/agents/failure-analyst.md +55 -0
- package/skills/capability-loop/agents/implementer.md +50 -0
- package/skills/capability-loop/agents/tester.md +53 -0
- package/skills/capability-loop/templates/capability-spec.md +118 -0
- package/skills/capability-loop/templates/failure-analysis.md +118 -0
- package/skills/characterization-test/agents/behavior-capturer.md +50 -0
- package/skills/characterization-test/agents/coverage-checker.md +54 -0
- package/skills/characterization-test/agents/reporter.md +50 -0
- package/skills/characterization-test/agents/test-writer.md +49 -0
- package/skills/characterization-test/rubrics/coverage-criteria.md +53 -0
- package/skills/characterization-test/templates/test-template.ts +101 -0
- package/skills/claude-md-guide/rubrics/anti-patterns.md +88 -0
- package/skills/claude-md-guide/templates/claude-md.md +54 -0
- package/skills/commerce-patterns/rubrics/checkout-flow.md +48 -0
- package/skills/commerce-patterns/templates/product-schema.md +85 -0
- package/skills/commit-push-pr/agents/change-analyzer.md +55 -0
- package/skills/commit-push-pr/agents/message-writer.md +50 -0
- package/skills/commit-push-pr/agents/pr-writer.md +58 -0
- package/skills/commit-push-pr/agents/reviewer.md +52 -0
- package/skills/commit-push-pr/rubrics/commit-message.md +73 -0
- package/skills/commit-push-pr/templates/pr-body.md +63 -0
- package/skills/context7-usage/rubrics/when-to-use.md +50 -0
- package/skills/create-prd/agents/edge-case-finder.md +48 -0
- package/skills/create-prd/agents/prioritizer.md +60 -0
- package/skills/create-prd/agents/requirements-writer.md +48 -0
- package/skills/create-prd/agents/researcher.md +55 -0
- package/skills/create-prd/agents/reviewer.md +54 -0
- package/skills/create-prd/frameworks/jobs-to-be-done.md +96 -0
- package/skills/create-prd/frameworks/rice-scoring.md +97 -0
- package/skills/create-prd/orchestrator.md +70 -0
- package/skills/create-prd/rubrics/completeness.md +58 -0
- package/skills/create-prd/templates/prd.md +139 -0
- package/skills/design-audit/agents/a11y-auditor.md +43 -0
- package/skills/design-audit/agents/performance-auditor.md +46 -0
- package/skills/design-audit/agents/responsive-auditor.md +46 -0
- package/skills/design-audit/agents/scorer.md +47 -0
- package/skills/design-audit/agents/slop-detector.md +47 -0
- package/skills/design-audit/frameworks/core-web-vitals.md +107 -0
- package/skills/design-audit/frameworks/wcag-checklist.md +64 -0
- package/skills/design-audit/orchestrator.md +64 -0
- package/skills/design-audit/rubrics/ai-slop-patterns.md +83 -0
- package/skills/design-audit/rubrics/scoring.md +63 -0
- package/skills/design-audit/templates/report.md +88 -0
- package/skills/design-critique/rubrics/ux-heuristics.md +143 -0
- package/skills/design-critique/templates/critique-report.md +86 -0
- package/skills/design-distill/templates/design-system.md +132 -0
- package/skills/design-normalize/rubrics/token-naming.md +117 -0
- package/skills/design-normalize/templates/token-audit.md +89 -0
- package/skills/design-polish/rubrics/polish-checklist.md +68 -0
- package/skills/design-polish/templates/polish-report.md +64 -0
- package/skills/design-teach/rubrics/brand-personality.md +73 -0
- package/skills/design-teach/templates/design-context.json +36 -0
- package/skills/e2e-commerce/templates/test-scenarios.md +170 -0
- package/skills/event-comms/templates/email-invite.md +99 -0
- package/skills/event-comms/templates/sns-post.md +133 -0
- package/skills/event-ops/rubrics/contingency.md +85 -0
- package/skills/event-ops/templates/d-day-checklist.md +65 -0
- package/skills/event-planning/rubrics/timeline.md +70 -0
- package/skills/event-planning/templates/event-plan.md +91 -0
- package/skills/exec-plan/agents/decomposer.md +47 -0
- package/skills/exec-plan/agents/dependency-mapper.md +44 -0
- package/skills/exec-plan/agents/estimator.md +43 -0
- package/skills/exec-plan/agents/validator.md +55 -0
- package/skills/exec-plan/orchestrator.md +70 -0
- package/skills/exec-plan/rubrics/complexity-scoring.md +75 -0
- package/skills/exec-plan/templates/plan.md +147 -0
- package/skills/git-worktree/rubrics/when-to-use.md +55 -0
- package/skills/handoff/agents/context-summarizer.md +51 -0
- package/skills/handoff/agents/document-writer.md +63 -0
- package/skills/handoff/agents/state-collector.md +53 -0
- package/skills/handoff/agents/verifier.md +48 -0
- package/skills/handoff/rubrics/completeness.md +62 -0
- package/skills/handoff/templates/handoff.md +107 -0
- package/skills/parallel-research/agents/best-practices.md +43 -0
- package/skills/parallel-research/agents/codebase-patterns.md +46 -0
- package/skills/parallel-research/agents/framework-docs.md +45 -0
- package/skills/parallel-research/agents/security-advisory.md +46 -0
- package/skills/parallel-research/agents/synthesizer.md +52 -0
- package/skills/parallel-research/experts/best-practices.md +50 -0
- package/skills/parallel-research/experts/codebase-patterns.md +70 -0
- package/skills/parallel-research/experts/framework-docs.md +65 -0
- package/skills/parallel-research/experts/security-advisory.md +69 -0
- package/skills/parallel-research/orchestrator.md +65 -0
- package/skills/parallel-research/templates/synthesis.md +101 -0
- package/skills/prioritization-frameworks/rubrics/frameworks.md +79 -0
- package/skills/prioritization-frameworks/templates/scoring-matrix.md +69 -0
- package/skills/priority-todos/rubrics/prioritization.md +70 -0
- package/skills/priority-todos/templates/todo-board.md +59 -0
- package/skills/seo-checklist/frameworks/structured-data.md +153 -0
- package/skills/seo-checklist/rubrics/content-seo.md +42 -0
- package/skills/seo-checklist/rubrics/technical-seo.md +48 -0
- package/skills/techdebt/agents/analyzer.md +50 -0
- package/skills/techdebt/agents/fixer.md +41 -0
- package/skills/techdebt/agents/reviewer.md +47 -0
- package/skills/techdebt/agents/scanner.md +44 -0
- package/skills/techdebt/orchestrator.md +70 -0
- package/skills/techdebt/rubrics/severity.md +51 -0
- package/skills/techdebt/scripts/scan.js +90 -0
- package/skills/techdebt/templates/report.md +86 -0
- package/skills/tool-fallback/rubrics/fallback-chain.md +58 -0
- package/skills/typescript-advanced-types/rubrics/type-patterns.md +109 -0
- package/skills/ui-ux-pro-max/rubrics/interaction-states.md +83 -0
- package/skills/ui-ux-pro-max/rubrics/responsive-breakpoints.md +99 -0
- package/skills/user-personas/rubrics/research-methods.md +56 -0
- package/skills/user-personas/templates/persona.md +89 -0
- package/skills/vercel-react-best-practices/rubrics/performance.md +82 -0
- package/skills/vercel-react-best-practices/rubrics/server-components.md +86 -0
- package/skills/vibe-docs/SKILL.md +171 -0
- package/skills/vibe-docs/templates/architecture.md +80 -0
- package/skills/vibe-docs/templates/readme.md +84 -0
- package/skills/vibe-docs/templates/release-notes.md +74 -0
- package/skills/vibe-figma/SKILL.md +173 -54
- package/skills/vibe-figma/rubrics/extraction-checklist.md +51 -0
- package/skills/vibe-figma/templates/figma-handoff.md +96 -0
- package/skills/vibe-figma-analyze/rubrics/analysis-dimensions.md +53 -0
- package/skills/vibe-figma-codegen/rubrics/code-quality.md +54 -0
- package/skills/vibe-figma-consolidate/templates/consolidation-report.md +95 -0
- package/skills/vibe-figma-convert/SKILL.md +176 -1
- package/skills/vibe-figma-convert/rubrics/conversion-rules.md +83 -0
- package/skills/vibe-figma-convert/templates/component.md +152 -0
- package/skills/vibe-figma-extract/rubrics/image-rules.md +67 -0
- package/skills/vibe-figma-frame/rubrics/frame-selection.md +55 -0
- package/skills/vibe-figma-pipeline/rubrics/pipeline-stages.md +96 -0
- package/skills/vibe-figma-rules/rubrics/naming-conventions.md +70 -0
- package/skills/vibe-figma-style/rubrics/style-mapping.md +100 -0
- package/skills/video-production/rubrics/quality-checklist.md +58 -0
- package/skills/video-production/templates/production-plan.md +104 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: arch-violation-checker
|
|
3
|
+
role: Scans all import statements across the codebase and flags boundary violations against the rule set
|
|
4
|
+
tools: [Glob, Grep, Read]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Arch Violation Checker
|
|
8
|
+
|
|
9
|
+
## Role
|
|
10
|
+
Performs the mechanical import-graph scan against the generated rule set. For every file in a `from` layer, it extracts all import paths and checks whether any resolve into a `cannotImport` layer. Reports each violation with full context.
|
|
11
|
+
|
|
12
|
+
## Responsibilities
|
|
13
|
+
- Enumerate all files matching each rule's `from` glob pattern
|
|
14
|
+
- Extract import and require statements from each file
|
|
15
|
+
- Resolve relative imports to their canonical layer classification
|
|
16
|
+
- Check resolved imports against the `cannotImport` glob patterns
|
|
17
|
+
- Collect violations with file path, line number, importing path, and violated rule
|
|
18
|
+
|
|
19
|
+
## Input
|
|
20
|
+
Normalized rule set JSON from `arch-rule-generator` and project root path.
|
|
21
|
+
|
|
22
|
+
## Output
|
|
23
|
+
Violation list JSON:
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"violations": [
|
|
27
|
+
{
|
|
28
|
+
"rule": "domain-no-infra",
|
|
29
|
+
"file": "src/domain/user.ts",
|
|
30
|
+
"line": 3,
|
|
31
|
+
"import": "../infra/db/userRepository",
|
|
32
|
+
"resolved": "src/infra/db/userRepository.ts",
|
|
33
|
+
"severity": "error"
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"scannedFiles": 142,
|
|
37
|
+
"cleanFiles": 139
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Communication
|
|
42
|
+
- Reports violation list to: `arch-reporter`
|
|
43
|
+
- Receives instructions from: arch-guard orchestrator (SKILL.md)
|
|
44
|
+
|
|
45
|
+
## Domain Knowledge
|
|
46
|
+
Import resolution rules:
|
|
47
|
+
- Relative imports (`./`, `../`) must be resolved relative to the importing file's location
|
|
48
|
+
- Path aliases (`@/`, `~/`) must be resolved using the project's `tsconfig.json` `paths` config
|
|
49
|
+
- External package imports (no leading `.` or `/`) are always allowed — skip them
|
|
50
|
+
- Re-export barrel files (`index.ts`) count as the directory they represent
|
|
51
|
+
- Type-only imports (`import type`) still count as dependencies for boundary purposes
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: clean-architecture
|
|
3
|
+
type: framework
|
|
4
|
+
applies-to: [arch-guard]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Clean Architecture — Reference Card
|
|
8
|
+
|
|
9
|
+
## Layer Model
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
┌─────────────────────────────────┐
|
|
13
|
+
│ Frameworks & Drivers │ ← UI, DB, HTTP, CLI, external APIs
|
|
14
|
+
├─────────────────────────────────┤
|
|
15
|
+
│ Interface Adapters │ ← Controllers, Presenters, Gateways
|
|
16
|
+
├─────────────────────────────────┤
|
|
17
|
+
│ Application Use Cases │ ← Business rules orchestration
|
|
18
|
+
├─────────────────────────────────┤
|
|
19
|
+
│ Entities (Domain) │ ← Core business objects & rules
|
|
20
|
+
└─────────────────────────────────┘
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Dependency Rule**: Dependencies point inward only. Inner layers know nothing about outer layers.
|
|
24
|
+
|
|
25
|
+
## Layer Responsibilities
|
|
26
|
+
|
|
27
|
+
| Layer | Contains | Must NOT contain |
|
|
28
|
+
|-------|----------|-----------------|
|
|
29
|
+
| Entities | Domain models, value objects, domain rules | Framework imports, DB calls |
|
|
30
|
+
| Use Cases | Application workflows, business logic | HTTP, DB drivers, UI logic |
|
|
31
|
+
| Adapters | Controllers, mappers, repository impls | Business rules, domain logic |
|
|
32
|
+
| Frameworks | Express routes, Prisma, React, CLI | Business or application logic |
|
|
33
|
+
|
|
34
|
+
## Dependency Rule in Code
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
// Good — Use Case depends on abstraction (repository interface)
|
|
38
|
+
// src/use-cases/CreateUser.ts
|
|
39
|
+
interface UserRepository { save(user: User): Promise<void> }
|
|
40
|
+
|
|
41
|
+
export class CreateUserUseCase {
|
|
42
|
+
constructor(private users: UserRepository) {}
|
|
43
|
+
execute(data: CreateUserInput): Promise<User> { /* business logic only */ }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Good — Adapter implements the interface
|
|
47
|
+
// src/adapters/PrismaUserRepository.ts
|
|
48
|
+
import { PrismaClient } from '@prisma/client'; // framework import OK here
|
|
49
|
+
class PrismaUserRepository implements UserRepository {
|
|
50
|
+
save(user: User): Promise<void> { /* prisma call */ }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Bad — Use Case imports Prisma directly (crosses boundary)
|
|
54
|
+
// src/use-cases/CreateUser.ts
|
|
55
|
+
import { PrismaClient } from '@prisma/client'; // VIOLATION
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Boundary Crossing Patterns
|
|
59
|
+
|
|
60
|
+
### Data Transfer Objects (DTOs)
|
|
61
|
+
Cross boundaries using plain data structures, not domain entities.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
// Input DTO — from outer layer into use case
|
|
65
|
+
type CreateUserInput = { email: string; name: string }
|
|
66
|
+
|
|
67
|
+
// Output DTO — from use case out to adapter
|
|
68
|
+
type CreateUserOutput = { id: string; email: string; createdAt: Date }
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Repository Pattern
|
|
72
|
+
Isolates data access behind an interface defined in the domain layer.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
// Defined in domain layer
|
|
76
|
+
interface UserRepository {
|
|
77
|
+
findById(id: string): Promise<User | null>
|
|
78
|
+
save(user: User): Promise<void>
|
|
79
|
+
delete(id: string): Promise<void>
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Common Violations
|
|
84
|
+
|
|
85
|
+
| Violation | Example | Fix |
|
|
86
|
+
|-----------|---------|-----|
|
|
87
|
+
| Framework import in entity | `import express from 'express'` in `User.ts` | Move to adapter layer |
|
|
88
|
+
| DB call in use case | `prisma.user.findMany()` in use case | Use repository interface |
|
|
89
|
+
| Business logic in controller | `if (price > 100) applyDiscount()` in route handler | Move to use case |
|
|
90
|
+
| Entity exposed via HTTP | Return `User` domain object as JSON directly | Map to response DTO |
|
|
91
|
+
| Use case depends on use case | `CreateOrder` imports `CreateUser` | Extract shared logic to domain service |
|
|
92
|
+
|
|
93
|
+
## Directory Structure Convention
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
src/
|
|
97
|
+
domain/ ← Entities, value objects, domain interfaces
|
|
98
|
+
use-cases/ ← Application business rules
|
|
99
|
+
adapters/ ← Controllers, repository implementations, mappers
|
|
100
|
+
infrastructure/ ← DB, HTTP, external services (framework layer)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Arch-Guard Checks
|
|
104
|
+
|
|
105
|
+
- No `import` crossing inward (outer → inner only)
|
|
106
|
+
- No framework imports (`express`, `prisma`, `mongoose`) in `domain/` or `use-cases/`
|
|
107
|
+
- No `fetch`/`axios` in entities or use cases
|
|
108
|
+
- All use case dependencies are interfaces, not concrete classes
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: solid-principles
|
|
3
|
+
type: framework
|
|
4
|
+
applies-to: [arch-guard]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# SOLID Principles — Reference Card
|
|
8
|
+
|
|
9
|
+
## S — Single Responsibility Principle
|
|
10
|
+
> A class/module should have only one reason to change.
|
|
11
|
+
|
|
12
|
+
**Violation signal**: A function does fetching + parsing + formatting + writing.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
// Bad — UserService handles auth AND email AND db writes
|
|
16
|
+
class UserService {
|
|
17
|
+
login(email: string, password: string): void { /* auth logic */ }
|
|
18
|
+
sendWelcomeEmail(user: User): void { /* email logic */ }
|
|
19
|
+
saveToDb(user: User): void { /* db logic */ }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Good — each class owns one concern
|
|
23
|
+
class AuthService { login(email: string, password: string): void {} }
|
|
24
|
+
class EmailService { sendWelcome(user: User): void {} }
|
|
25
|
+
class UserRepository { save(user: User): void {} }
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## O — Open/Closed Principle
|
|
29
|
+
> Open for extension, closed for modification.
|
|
30
|
+
|
|
31
|
+
**Violation signal**: Adding a new type requires editing existing switch/if chains.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
// Bad — adding payment type requires editing processPayment
|
|
35
|
+
function processPayment(type: string, amount: number): void {
|
|
36
|
+
if (type === 'card') { /* ... */ }
|
|
37
|
+
if (type === 'paypal') { /* ... */ }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Good — extend via new class, no existing code changes
|
|
41
|
+
interface PaymentProcessor { process(amount: number): void }
|
|
42
|
+
class CardProcessor implements PaymentProcessor { process(amount: number): void {} }
|
|
43
|
+
class PayPalProcessor implements PaymentProcessor { process(amount: number): void {} }
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## L — Liskov Substitution Principle
|
|
47
|
+
> Subtypes must be substitutable for their base types.
|
|
48
|
+
|
|
49
|
+
**Violation signal**: Overriding a method to throw `NotImplementedError` or changing preconditions.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
// Bad — Square breaks Rectangle's invariant (width/height independence)
|
|
53
|
+
class Rectangle { setWidth(w: number): void {} setHeight(h: number): void {} }
|
|
54
|
+
class Square extends Rectangle {
|
|
55
|
+
setWidth(w: number): void { this.width = w; this.height = w; } // breaks contract
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Good — separate types, shared interface
|
|
59
|
+
interface Shape { area(): number }
|
|
60
|
+
class Rectangle implements Shape { area(): number { return this.w * this.h; } }
|
|
61
|
+
class Square implements Shape { area(): number { return this.side ** 2; } }
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## I — Interface Segregation Principle
|
|
65
|
+
> Clients should not depend on interfaces they do not use.
|
|
66
|
+
|
|
67
|
+
**Violation signal**: Implementing an interface and leaving methods as `() => { throw new Error() }`.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
// Bad — Printer forced to implement fax() it doesn't support
|
|
71
|
+
interface Machine { print(): void; scan(): void; fax(): void; }
|
|
72
|
+
|
|
73
|
+
// Good — split into focused interfaces
|
|
74
|
+
interface Printer { print(): void }
|
|
75
|
+
interface Scanner { scan(): void }
|
|
76
|
+
interface FaxMachine { fax(): void }
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## D — Dependency Inversion Principle
|
|
80
|
+
> Depend on abstractions, not concretions.
|
|
81
|
+
|
|
82
|
+
**Violation signal**: High-level module imports a specific low-level class directly.
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// Bad — OrderService tightly coupled to MySQLDatabase
|
|
86
|
+
import { MySQLDatabase } from './MySQLDatabase';
|
|
87
|
+
class OrderService { db = new MySQLDatabase(); }
|
|
88
|
+
|
|
89
|
+
// Good — depend on interface, inject implementation
|
|
90
|
+
interface Database { query(sql: string): unknown[] }
|
|
91
|
+
class OrderService { constructor(private db: Database) {} }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Quick Checklist
|
|
95
|
+
|
|
96
|
+
| Principle | Red Flag |
|
|
97
|
+
|-----------|----------|
|
|
98
|
+
| SRP | Function/class name contains "And" or "Manager" |
|
|
99
|
+
| OCP | Adding feature requires editing existing if/switch |
|
|
100
|
+
| LSP | Subclass throws `NotImplemented` or removes behavior |
|
|
101
|
+
| ISP | Interface has methods unused by most implementors |
|
|
102
|
+
| DIP | `new ConcreteClass()` inside a high-level module |
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* arch-guard/scripts/check-boundaries.js
|
|
4
|
+
* Read arch-rules.json and scan imports for violations.
|
|
5
|
+
* Usage: node check-boundaries.js [arch-rules.json] [src-dir]
|
|
6
|
+
* Output: JSON array of violations to stdout.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
|
|
12
|
+
const IMPORT_RE = /(?:import|from|require)\s*\(?['"]([^'"]+)['"]\)?/g;
|
|
13
|
+
const CODE_EXTS = new Set(['.ts', '.tsx', '.js', '.jsx']);
|
|
14
|
+
|
|
15
|
+
/** @returns {string[]} */
|
|
16
|
+
function collectFiles(dir) {
|
|
17
|
+
if (!fs.existsSync(dir)) return [];
|
|
18
|
+
const results = [];
|
|
19
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
20
|
+
if (entry.name.startsWith('.') || entry.name === 'node_modules' || entry.name === 'dist') continue;
|
|
21
|
+
const full = path.join(dir, entry.name);
|
|
22
|
+
if (entry.isDirectory()) results.push(...collectFiles(full));
|
|
23
|
+
else if (CODE_EXTS.has(path.extname(entry.name))) results.push(full);
|
|
24
|
+
}
|
|
25
|
+
return results;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** @param {string} pattern @param {string} filePath @returns {boolean} */
|
|
29
|
+
function matchesGlob(pattern, filePath) {
|
|
30
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
31
|
+
const regexStr = pattern
|
|
32
|
+
.replace(/\\/g, '/')
|
|
33
|
+
.replace(/\./g, '\\.')
|
|
34
|
+
.replace(/\*\*/g, '__DOUBLE__')
|
|
35
|
+
.replace(/\*/g, '[^/]+')
|
|
36
|
+
.replace(/__DOUBLE__/g, '.+');
|
|
37
|
+
return new RegExp(`^${regexStr}$`).test(normalized);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** @param {string} file @returns {string[]} */
|
|
41
|
+
function extractImports(file) {
|
|
42
|
+
const content = fs.readFileSync(file, 'utf-8');
|
|
43
|
+
const imports = [];
|
|
44
|
+
let m;
|
|
45
|
+
IMPORT_RE.lastIndex = 0;
|
|
46
|
+
while ((m = IMPORT_RE.exec(content)) !== null) imports.push(m[1]);
|
|
47
|
+
return imports;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** @param {string} fromFile @param {string} imp @param {string} baseDir @returns {string} */
|
|
51
|
+
function resolveImport(fromFile, imp, baseDir) {
|
|
52
|
+
if (!imp.startsWith('.')) return imp;
|
|
53
|
+
return path.resolve(path.dirname(fromFile), imp).replace(baseDir + path.sep, '').replace(/\\/g, '/');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const rulesPath = process.argv[2] || '.claude/vibe/arch-rules.json';
|
|
57
|
+
const srcDir = path.resolve(process.argv[3] || 'src');
|
|
58
|
+
const baseDir = path.resolve('.');
|
|
59
|
+
|
|
60
|
+
if (!fs.existsSync(rulesPath)) {
|
|
61
|
+
process.stderr.write(`arch-rules.json not found: ${rulesPath}\n`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const { rules } = JSON.parse(fs.readFileSync(rulesPath, 'utf-8'));
|
|
66
|
+
const files = collectFiles(srcDir);
|
|
67
|
+
const violations = [];
|
|
68
|
+
|
|
69
|
+
for (const rule of rules) {
|
|
70
|
+
const fromFiles = files.filter(f => matchesGlob(rule.from, f.replace(baseDir + path.sep, '').replace(/\\/g, '/')));
|
|
71
|
+
for (const file of fromFiles) {
|
|
72
|
+
const imports = extractImports(file);
|
|
73
|
+
for (const imp of imports) {
|
|
74
|
+
const resolved = resolveImport(file, imp, baseDir);
|
|
75
|
+
const forbidden = (rule.cannotImport || []).some(pat => matchesGlob(pat, resolved) || resolved.includes(pat.replace('/**', '').replace('**/', '')));
|
|
76
|
+
if (forbidden) {
|
|
77
|
+
violations.push({
|
|
78
|
+
rule: rule.name,
|
|
79
|
+
file: file.replace(baseDir + path.sep, '').replace(/\\/g, '/'),
|
|
80
|
+
import: imp,
|
|
81
|
+
resolved,
|
|
82
|
+
reason: rule.reason || `Violates rule: ${rule.name}`,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
process.stdout.write(JSON.stringify(violations, null, 2) + '\n');
|
|
90
|
+
if (violations.length > 0) process.exit(1);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Architecture boundary rules for arch-guard. Copy to .claude/vibe/arch-rules.json and customize.",
|
|
3
|
+
"rules": [
|
|
4
|
+
{
|
|
5
|
+
"name": "services-no-ui",
|
|
6
|
+
"from": "src/services/**",
|
|
7
|
+
"cannotImport": ["src/components/**", "src/pages/**", "src/app/**"],
|
|
8
|
+
"canImport": ["src/models/**", "src/utils/**", "src/types/**"],
|
|
9
|
+
"reason": "Services must be UI-agnostic for testability and reuse"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "domain-no-infra",
|
|
13
|
+
"from": "src/domain/**",
|
|
14
|
+
"cannotImport": ["src/infra/**", "src/db/**", "src/adapters/**"],
|
|
15
|
+
"canImport": ["src/domain/**", "src/types/**"],
|
|
16
|
+
"reason": "Domain layer must not depend on infrastructure (Clean Architecture)"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "components-no-pages",
|
|
20
|
+
"from": "src/components/**",
|
|
21
|
+
"cannotImport": ["src/pages/**", "src/app/**"],
|
|
22
|
+
"canImport": ["src/components/**", "src/hooks/**", "src/utils/**", "src/types/**"],
|
|
23
|
+
"reason": "Shared components must not import from page-level modules"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "lib-no-components",
|
|
27
|
+
"from": "src/lib/**",
|
|
28
|
+
"cannotImport": ["src/components/**", "src/pages/**"],
|
|
29
|
+
"canImport": ["src/lib/**", "src/types/**"],
|
|
30
|
+
"reason": "Library utilities must be framework-agnostic"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "models-no-controllers",
|
|
34
|
+
"from": "src/models/**",
|
|
35
|
+
"cannotImport": ["src/controllers/**", "src/handlers/**", "src/routes/**"],
|
|
36
|
+
"canImport": ["src/models/**", "src/types/**"],
|
|
37
|
+
"reason": "Models must not depend on request/response layer (MVC)"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "no-direct-db-in-handlers",
|
|
41
|
+
"from": "src/handlers/**",
|
|
42
|
+
"cannotImport": ["src/db/**", "src/repositories/**"],
|
|
43
|
+
"canImport": ["src/services/**", "src/types/**"],
|
|
44
|
+
"reason": "Handlers must use services, not access the database directly"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Architecture Violation Report
|
|
2
|
+
|
|
3
|
+
**Project**: {{PROJECT_NAME}}
|
|
4
|
+
**Date**: {{DATE}}
|
|
5
|
+
**Rules File**: {{RULES_FILE}}
|
|
6
|
+
**Total Violations**: {{VIOLATION_COUNT}}
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
| Rule | Violations |
|
|
13
|
+
|------|-----------|
|
|
14
|
+
{{RULE_SUMMARY_TABLE}}
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Violations by Rule
|
|
19
|
+
|
|
20
|
+
{{VIOLATIONS_BY_RULE}}
|
|
21
|
+
|
|
22
|
+
<!-- Example entry:
|
|
23
|
+
### services-no-ui (3 violations)
|
|
24
|
+
|
|
25
|
+
**Rule**: Services must be UI-agnostic for testability and reuse
|
|
26
|
+
|
|
27
|
+
| File | Forbidden Import |
|
|
28
|
+
|------|-----------------|
|
|
29
|
+
| src/services/auth.ts | src/components/Button.tsx |
|
|
30
|
+
| src/services/user.ts | src/pages/dashboard/index.ts |
|
|
31
|
+
-->
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## How to Fix
|
|
36
|
+
|
|
37
|
+
For each violation, choose one:
|
|
38
|
+
|
|
39
|
+
1. **Move the dependency** — relocate shared logic to a layer both sides can import
|
|
40
|
+
2. **Invert the dependency** — use an interface/callback instead of a direct import
|
|
41
|
+
3. **Promote the import** — move the imported file to a shared/common layer
|
|
42
|
+
4. **Update the rule** — if the violation is intentional, document why and update arch-rules.json
|
|
43
|
+
|
|
44
|
+
> Do NOT suppress violations without documenting the reason in arch-rules.json.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Next Steps
|
|
49
|
+
|
|
50
|
+
1. Fix all violations in the table above
|
|
51
|
+
2. Re-run: `node skills/arch-guard/scripts/check-boundaries.js {{RULES_FILE}} {{SRC_DIR}}`
|
|
52
|
+
3. Commit clean state: `git commit -m "fix: resolve arch-guard boundary violations"`
|
|
53
|
+
4. Add to CI: run check-boundaries.js in pre-commit or CI pipeline
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Required Brand Assets Checklist
|
|
2
|
+
|
|
3
|
+
Complete this checklist before shipping. Each missing item is a gap in brand completeness.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Tier 1 — Blocking (must exist before launch)
|
|
8
|
+
|
|
9
|
+
### Favicon & App Icons
|
|
10
|
+
|
|
11
|
+
- [ ] `favicon.ico` — 16×16, 32×32, 48×48 combined
|
|
12
|
+
- [ ] `favicon-16x16.png`
|
|
13
|
+
- [ ] `favicon-32x32.png`
|
|
14
|
+
- [ ] `apple-touch-icon.png` — 180×180
|
|
15
|
+
- [ ] `android-chrome-192x192.png`
|
|
16
|
+
- [ ] `android-chrome-512x512.png`
|
|
17
|
+
- [ ] `site.webmanifest` — references all icon paths, correct `name` and `theme_color`
|
|
18
|
+
|
|
19
|
+
### Logo
|
|
20
|
+
|
|
21
|
+
- [ ] Primary logo (SVG) — color version
|
|
22
|
+
- [ ] Primary logo (SVG) — white/reversed version for dark backgrounds
|
|
23
|
+
- [ ] Icon-only version (SVG) — usable at 32px minimum
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Tier 2 — Important (should exist before public launch)
|
|
28
|
+
|
|
29
|
+
### Open Graph / Social Sharing
|
|
30
|
+
|
|
31
|
+
- [ ] `og-image.png` — 1200×630px, includes logo and product name
|
|
32
|
+
- [ ] `twitter-image.png` — 1200×600px or reuse OG image
|
|
33
|
+
- [ ] OG meta tags in `<head>`: `og:title`, `og:description`, `og:image`, `og:url`
|
|
34
|
+
- [ ] Twitter card meta tags: `twitter:card`, `twitter:image`
|
|
35
|
+
|
|
36
|
+
### iOS / PWA
|
|
37
|
+
|
|
38
|
+
- [ ] `apple-touch-icon.png` correctly linked in `<head>`
|
|
39
|
+
- [ ] `maskable_icon.png` — 512×512, safe zone within inner 80% (for Android adaptive icons)
|
|
40
|
+
- [ ] PWA manifest includes `purpose: "any maskable"` entry
|
|
41
|
+
- [ ] `theme-color` meta tag set to brand primary color
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Tier 3 — Complete (production-quality brand presence)
|
|
46
|
+
|
|
47
|
+
### Email Assets
|
|
48
|
+
|
|
49
|
+
- [ ] Email header logo — 300×80px max, hosted URL (not local path)
|
|
50
|
+
- [ ] Email footer logo — monochrome version
|
|
51
|
+
|
|
52
|
+
### Documentation / Marketing
|
|
53
|
+
|
|
54
|
+
- [ ] Logo usage guidelines documented
|
|
55
|
+
- [ ] Color codes documented (HEX, RGB, HSL)
|
|
56
|
+
- [ ] Font names and weights documented
|
|
57
|
+
- [ ] Do/don't logo usage examples
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Quality Checks
|
|
62
|
+
|
|
63
|
+
### Icon Quality
|
|
64
|
+
|
|
65
|
+
- [ ] Icon is recognizable at 16×16 (no fine details lost)
|
|
66
|
+
- [ ] No text or letters in icon (illegible at small sizes)
|
|
67
|
+
- [ ] Single focal element (not a scene or complex composition)
|
|
68
|
+
- [ ] Works on both white and dark backgrounds
|
|
69
|
+
- [ ] Consistent visual weight with similar products in the app's ecosystem
|
|
70
|
+
|
|
71
|
+
### File Formats
|
|
72
|
+
|
|
73
|
+
- [ ] SVG files are clean (no Figma/Illustrator junk metadata)
|
|
74
|
+
- [ ] PNG files are optimized (use `pngcrush` or equivalent)
|
|
75
|
+
- [ ] ICO file contains all three sizes (16, 32, 48)
|
|
76
|
+
- [ ] All files referenced in manifest actually exist
|
|
77
|
+
|
|
78
|
+
### Colors in Assets
|
|
79
|
+
|
|
80
|
+
- [ ] Icon colors match brand color palette exactly (no approximations)
|
|
81
|
+
- [ ] OG image background uses brand color, not generic gray
|
|
82
|
+
- [ ] Logo SVG uses `currentColor` or hardcoded brand values (never browser defaults)
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Asset Inventory
|
|
87
|
+
|
|
88
|
+
| Asset | File Path | Size | Format | Status |
|
|
89
|
+
|-------|-----------|------|--------|--------|
|
|
90
|
+
| Primary logo | {{LOGO_PATH}} | — | SVG | {{STATUS}} |
|
|
91
|
+
| Logo white | {{LOGO_WHITE_PATH}} | — | SVG | {{STATUS}} |
|
|
92
|
+
| App icon | {{ICON_PATH}} | 512×512 | PNG | {{STATUS}} |
|
|
93
|
+
| Favicon bundle | `public/favicon.ico` | 16/32/48 | ICO | {{STATUS}} |
|
|
94
|
+
| Apple touch | `public/apple-touch-icon.png` | 180×180 | PNG | {{STATUS}} |
|
|
95
|
+
| Android 192 | `public/android-chrome-192x192.png` | 192×192 | PNG | {{STATUS}} |
|
|
96
|
+
| Android 512 | `public/android-chrome-512x512.png` | 512×512 | PNG | {{STATUS}} |
|
|
97
|
+
| OG image | `public/og-image.png` | 1200×630 | PNG | {{STATUS}} |
|
|
98
|
+
| Maskable icon | `public/maskable-icon.png` | 512×512 | PNG | {{STATUS}} |
|