@su-record/vibe 2.8.24 → 2.8.26
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/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 +122 -206
- 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 +13 -175
- 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,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: structured-data
|
|
3
|
+
type: framework
|
|
4
|
+
applies-to: [seo-checklist]
|
|
5
|
+
format: JSON-LD
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Structured Data — JSON-LD Schema Templates
|
|
9
|
+
|
|
10
|
+
Embed in `<script type="application/ld+json">` in `<head>` or before `</body>`.
|
|
11
|
+
|
|
12
|
+
## Article
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"@context": "https://schema.org",
|
|
17
|
+
"@type": "Article",
|
|
18
|
+
"headline": "Article Title (max 110 chars)",
|
|
19
|
+
"description": "Article summary (max 160 chars)",
|
|
20
|
+
"image": "https://example.com/article-image.jpg",
|
|
21
|
+
"author": {
|
|
22
|
+
"@type": "Person",
|
|
23
|
+
"name": "Author Name",
|
|
24
|
+
"url": "https://example.com/authors/name"
|
|
25
|
+
},
|
|
26
|
+
"publisher": {
|
|
27
|
+
"@type": "Organization",
|
|
28
|
+
"name": "Publisher Name",
|
|
29
|
+
"logo": {
|
|
30
|
+
"@type": "ImageObject",
|
|
31
|
+
"url": "https://example.com/logo.png"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"datePublished": "2024-01-15T08:00:00+00:00",
|
|
35
|
+
"dateModified": "2024-01-20T10:00:00+00:00",
|
|
36
|
+
"mainEntityOfPage": {
|
|
37
|
+
"@type": "WebPage",
|
|
38
|
+
"@id": "https://example.com/article-slug"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Required by Google**: `headline`, `image`, `datePublished`, `author`
|
|
44
|
+
|
|
45
|
+
## Product
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"@context": "https://schema.org",
|
|
50
|
+
"@type": "Product",
|
|
51
|
+
"name": "Product Name",
|
|
52
|
+
"description": "Product description",
|
|
53
|
+
"image": ["https://example.com/product-1.jpg", "https://example.com/product-2.jpg"],
|
|
54
|
+
"sku": "PROD-123",
|
|
55
|
+
"brand": {
|
|
56
|
+
"@type": "Brand",
|
|
57
|
+
"name": "Brand Name"
|
|
58
|
+
},
|
|
59
|
+
"offers": {
|
|
60
|
+
"@type": "Offer",
|
|
61
|
+
"url": "https://example.com/product",
|
|
62
|
+
"priceCurrency": "USD",
|
|
63
|
+
"price": "29.99",
|
|
64
|
+
"availability": "https://schema.org/InStock",
|
|
65
|
+
"itemCondition": "https://schema.org/NewCondition"
|
|
66
|
+
},
|
|
67
|
+
"aggregateRating": {
|
|
68
|
+
"@type": "AggregateRating",
|
|
69
|
+
"ratingValue": "4.5",
|
|
70
|
+
"reviewCount": "127"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Required by Google**: `name` + one of `review`, `aggregateRating`, or `offers`
|
|
76
|
+
|
|
77
|
+
## FAQ
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"@context": "https://schema.org",
|
|
82
|
+
"@type": "FAQPage",
|
|
83
|
+
"mainEntity": [
|
|
84
|
+
{
|
|
85
|
+
"@type": "Question",
|
|
86
|
+
"name": "What is the return policy?",
|
|
87
|
+
"acceptedAnswer": {
|
|
88
|
+
"@type": "Answer",
|
|
89
|
+
"text": "We accept returns within 30 days of purchase. Items must be unused and in original packaging."
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"@type": "Question",
|
|
94
|
+
"name": "How long does shipping take?",
|
|
95
|
+
"acceptedAnswer": {
|
|
96
|
+
"@type": "Answer",
|
|
97
|
+
"text": "Standard shipping takes 3-5 business days. Express shipping is available for 1-2 day delivery."
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Note**: Each Q&A must appear as visible content on the page. Do not use for ad content.
|
|
105
|
+
|
|
106
|
+
## BreadcrumbList
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"@context": "https://schema.org",
|
|
111
|
+
"@type": "BreadcrumbList",
|
|
112
|
+
"itemListElement": [
|
|
113
|
+
{
|
|
114
|
+
"@type": "ListItem",
|
|
115
|
+
"position": 1,
|
|
116
|
+
"name": "Home",
|
|
117
|
+
"item": "https://example.com"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"@type": "ListItem",
|
|
121
|
+
"position": 2,
|
|
122
|
+
"name": "Category",
|
|
123
|
+
"item": "https://example.com/category"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"@type": "ListItem",
|
|
127
|
+
"position": 3,
|
|
128
|
+
"name": "Product Name",
|
|
129
|
+
"item": "https://example.com/category/product"
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Note**: `position` must be sequential starting at 1. Last item does not require `item` URL.
|
|
136
|
+
|
|
137
|
+
## Validation
|
|
138
|
+
|
|
139
|
+
| Tool | URL |
|
|
140
|
+
|------|-----|
|
|
141
|
+
| Google Rich Results Test | https://search.google.com/test/rich-results |
|
|
142
|
+
| Schema.org Validator | https://validator.schema.org |
|
|
143
|
+
| Chrome DevTools → Network | Filter for `application/ld+json` |
|
|
144
|
+
|
|
145
|
+
## Common Mistakes
|
|
146
|
+
|
|
147
|
+
| Mistake | Fix |
|
|
148
|
+
|---------|-----|
|
|
149
|
+
| Price without currency | Always include `priceCurrency` with `price` |
|
|
150
|
+
| Missing `datePublished` on Article | Required for Google News eligibility |
|
|
151
|
+
| FAQ content not visible on page | Google penalizes hidden Q&A markup |
|
|
152
|
+
| Breadcrumb positions not sequential | Use 1, 2, 3 — no skipping |
|
|
153
|
+
| Image URL not absolute | Always use full `https://` URLs |
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Content SEO Checklist
|
|
2
|
+
|
|
3
|
+
## Heading Structure
|
|
4
|
+
|
|
5
|
+
- [ ] Single `<h1>` per page — matches primary keyword intent
|
|
6
|
+
- [ ] Logical hierarchy: `h1 → h2 → h3` (no skipping levels)
|
|
7
|
+
- [ ] `<h2>` tags cover major subtopics (crawlers use for content outline)
|
|
8
|
+
- [ ] No headings used purely for styling — use CSS classes instead
|
|
9
|
+
|
|
10
|
+
## Keyword Placement
|
|
11
|
+
|
|
12
|
+
- [ ] Primary keyword in `<title>`, `<h1>`, first 100 words of body
|
|
13
|
+
- [ ] Secondary keywords in `<h2>` tags and body naturally
|
|
14
|
+
- [ ] Keyword in image `alt` text where relevant (descriptive, not stuffed)
|
|
15
|
+
- [ ] URL slug contains primary keyword (lowercase, hyphens, no stop words)
|
|
16
|
+
|
|
17
|
+
## Internal Linking
|
|
18
|
+
|
|
19
|
+
- [ ] Every important page reachable within 3 clicks from homepage
|
|
20
|
+
- [ ] Anchor text is descriptive ("authentication guide") not generic ("click here")
|
|
21
|
+
- [ ] New content links back to related existing content
|
|
22
|
+
- [ ] Orphan pages (no inbound internal links) have at least one link added
|
|
23
|
+
|
|
24
|
+
## Content Quality Signals
|
|
25
|
+
|
|
26
|
+
- [ ] Word count appropriate for topic depth (informational: 1000+, landing: 300-600)
|
|
27
|
+
- [ ] No duplicate content across pages — each URL has unique value
|
|
28
|
+
- [ ] Pagination uses `rel="next"` / `rel="prev"` or canonical to main page
|
|
29
|
+
- [ ] Thin content pages (< 300 words) either expanded or `noindex` applied
|
|
30
|
+
|
|
31
|
+
## Images & Media
|
|
32
|
+
|
|
33
|
+
- [ ] Every `<img>` has descriptive `alt` text (empty `alt=""` for decorative images)
|
|
34
|
+
- [ ] File names descriptive: `product-dashboard-screenshot.webp` not `IMG_4821.jpg`
|
|
35
|
+
- [ ] Use WebP or AVIF format where possible
|
|
36
|
+
- [ ] Videos have transcript or caption for accessibility and crawlability
|
|
37
|
+
|
|
38
|
+
## Localization (if applicable)
|
|
39
|
+
|
|
40
|
+
- [ ] `hreflang` tags on all translated pages
|
|
41
|
+
- [ ] Each locale version has its own canonical URL
|
|
42
|
+
- [ ] `hreflang` includes `x-default` for language selector page
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Technical SEO Checklist
|
|
2
|
+
|
|
3
|
+
## Meta Tags
|
|
4
|
+
|
|
5
|
+
- [ ] `<title>` unique per page, 50-60 characters
|
|
6
|
+
- [ ] `<meta name="description">` unique per page, 150-160 characters
|
|
7
|
+
- [ ] `<link rel="canonical">` on every page (including paginated, filtered)
|
|
8
|
+
- [ ] `<meta name="robots" content="index,follow">` — verify `noindex` is NOT in production
|
|
9
|
+
- [ ] `<html lang="{{LOCALE}}">` set correctly
|
|
10
|
+
|
|
11
|
+
## Open Graph / Social
|
|
12
|
+
|
|
13
|
+
- [ ] `og:title` — matches page title or optimized variant
|
|
14
|
+
- [ ] `og:description` — matches meta description or optimized variant
|
|
15
|
+
- [ ] `og:image` — exactly **1200x630px**, under 8MB
|
|
16
|
+
- [ ] `og:type` — `website` for homepage, `article` for posts, `product` for products
|
|
17
|
+
- [ ] `og:url` — canonical URL
|
|
18
|
+
- [ ] `twitter:card` — `summary_large_image` for image-rich pages
|
|
19
|
+
- [ ] `twitter:image` — same as og:image (some crawlers check separately)
|
|
20
|
+
|
|
21
|
+
## Structured Data (JSON-LD)
|
|
22
|
+
|
|
23
|
+
- [ ] Correct `@type` for content: `Article`, `Product`, `FAQPage`, `LocalBusiness`, `BreadcrumbList`
|
|
24
|
+
- [ ] `BreadcrumbList` on all non-root pages
|
|
25
|
+
- [ ] Validated with [Google Rich Results Test](https://search.google.com/test/rich-results)
|
|
26
|
+
- [ ] No structured data describing content not visible on the page
|
|
27
|
+
|
|
28
|
+
## Crawlability
|
|
29
|
+
|
|
30
|
+
- [ ] `robots.txt` present at domain root
|
|
31
|
+
- `Allow: /` for public pages
|
|
32
|
+
- `Disallow: /api/`, `/admin/`, `/_next/` (static assets excepted)
|
|
33
|
+
- `Sitemap: https://{{DOMAIN}}/sitemap.xml`
|
|
34
|
+
- [ ] `sitemap.xml` auto-generated, includes `<lastmod>` with real dates
|
|
35
|
+
- [ ] Sitemap submitted to Google Search Console
|
|
36
|
+
|
|
37
|
+
## Performance (Core Web Vitals)
|
|
38
|
+
|
|
39
|
+
| Metric | Target | Common Fix |
|
|
40
|
+
|--------|--------|------------|
|
|
41
|
+
| LCP | ≤ 2.5s | `<link rel="preload">` on hero image |
|
|
42
|
+
| INP | ≤ 200ms | Defer non-critical JS |
|
|
43
|
+
| CLS | ≤ 0.1 | Set `width`/`height` on all images; `min-height` on dynamic containers |
|
|
44
|
+
|
|
45
|
+
- [ ] Images have explicit `width` and `height` attributes
|
|
46
|
+
- [ ] Below-fold images use `loading="lazy"`
|
|
47
|
+
- [ ] Hero/LCP image uses `fetchpriority="high"` (not lazy)
|
|
48
|
+
- [ ] No render-blocking scripts without `defer` or `async`
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: techdebt-analyzer
|
|
3
|
+
role: Analyzes severity and blast radius of each scanned finding
|
|
4
|
+
tools: [Read, Grep]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Techdebt Analyzer
|
|
8
|
+
|
|
9
|
+
## Role
|
|
10
|
+
Receives raw scan findings and evaluates each item's severity, effort to fix, and risk of breakage. Classifies findings into auto-fixable vs. manual-review categories and assigns a priority score to guide the fixer.
|
|
11
|
+
|
|
12
|
+
## Responsibilities
|
|
13
|
+
- Classify each finding by severity: Critical / High / Medium / Low
|
|
14
|
+
- Assess auto-fix safety: safe (delete line), risky (needs refactor), manual-only
|
|
15
|
+
- Estimate fix effort: trivial (1 line), minor (< 10 lines), major (multi-file)
|
|
16
|
+
- Detect clusters — multiple related findings that should be fixed together
|
|
17
|
+
- Flag findings in test files separately (lower priority, different rules apply)
|
|
18
|
+
|
|
19
|
+
## Input
|
|
20
|
+
Raw findings JSON array from `techdebt-scanner` with file, line, category, and snippet fields.
|
|
21
|
+
|
|
22
|
+
## Output
|
|
23
|
+
Enriched findings list with severity and fix metadata:
|
|
24
|
+
```json
|
|
25
|
+
[
|
|
26
|
+
{
|
|
27
|
+
"category": "console-log",
|
|
28
|
+
"file": "src/api/auth.ts",
|
|
29
|
+
"line": 12,
|
|
30
|
+
"snippet": "console.log(token)",
|
|
31
|
+
"severity": "High",
|
|
32
|
+
"autoFixable": true,
|
|
33
|
+
"effort": "trivial",
|
|
34
|
+
"fixMethod": "delete-line"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
```
|
|
38
|
+
Plus a summary: total counts by severity, estimated total fix time.
|
|
39
|
+
|
|
40
|
+
## Communication
|
|
41
|
+
- Reports enriched findings to: `techdebt-fixer` (auto-fixable items) and orchestrator (manual items)
|
|
42
|
+
- Receives instructions from: techdebt orchestrator (SKILL.md)
|
|
43
|
+
|
|
44
|
+
## Domain Knowledge
|
|
45
|
+
Severity heuristics:
|
|
46
|
+
- **Critical**: `any` in public API surface, `console.log` logging credentials/tokens
|
|
47
|
+
- **High**: `any` in business logic, `console.log` in production paths
|
|
48
|
+
- **Medium**: magic numbers, unused imports, commented-out blocks
|
|
49
|
+
- **Low**: unused imports in test files, minor style issues
|
|
50
|
+
Auto-fix safety rules: never auto-fix type changes, logic extractions, or multi-file changes.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: techdebt-fixer
|
|
3
|
+
role: Generates safe auto-fix patches for trivially fixable techdebt items
|
|
4
|
+
tools: [Read, Edit]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Techdebt Fixer
|
|
8
|
+
|
|
9
|
+
## Role
|
|
10
|
+
Applies safe, deterministic fixes to auto-fixable findings identified by the analyzer. Operates strictly within the boundaries set by the analyzer — never attempts fixes marked `manual-only` or `risky`. Each fix is atomic and targets a single file at a time.
|
|
11
|
+
|
|
12
|
+
## Responsibilities
|
|
13
|
+
- Delete `console.log`, `console.error`, `console.warn`, and `debugger` lines
|
|
14
|
+
- Remove unused import statements (single-identifier and named imports)
|
|
15
|
+
- Delete commented-out code blocks that contain dead code constructs
|
|
16
|
+
- Preserve surrounding blank lines and indentation conventions
|
|
17
|
+
- Record every change made for the reviewer's diff check
|
|
18
|
+
|
|
19
|
+
## Input
|
|
20
|
+
Filtered findings list from `techdebt-analyzer` where `autoFixable: true` and `effort: "trivial"`, plus the full file content via Read.
|
|
21
|
+
|
|
22
|
+
## Output
|
|
23
|
+
A change log of all edits applied:
|
|
24
|
+
```json
|
|
25
|
+
[
|
|
26
|
+
{ "file": "src/api/auth.ts", "line": 12, "action": "deleted", "was": "console.log(token)" },
|
|
27
|
+
{ "file": "src/components/Button.tsx", "line": 3, "action": "deleted", "was": "import React from 'react'" }
|
|
28
|
+
]
|
|
29
|
+
```
|
|
30
|
+
Edited files are modified in place using the Edit tool.
|
|
31
|
+
|
|
32
|
+
## Communication
|
|
33
|
+
- Reports change log to: `techdebt-reviewer`
|
|
34
|
+
- Receives instructions from: techdebt orchestrator (SKILL.md)
|
|
35
|
+
|
|
36
|
+
## Domain Knowledge
|
|
37
|
+
Fix safety rules:
|
|
38
|
+
- Only delete lines — never rewrite or rearrange code
|
|
39
|
+
- When removing a named import `{ A, B }`, if only `A` is unused, rewrite to `{ B }`, not delete the line
|
|
40
|
+
- Never remove imports flagged as side-effect imports (e.g., `import './styles.css'`)
|
|
41
|
+
- Stop and escalate if a file has been modified by another agent in the same session
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: techdebt-reviewer
|
|
3
|
+
role: Reviews auto-fix patches for correctness and safety before presenting to user
|
|
4
|
+
tools: [Read, Grep]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Techdebt Reviewer
|
|
8
|
+
|
|
9
|
+
## Role
|
|
10
|
+
Acts as the final quality gate before fixes are presented to the user for confirmation. Re-reads every modified file, verifies that only the intended lines were changed, and checks that no new issues were introduced. Produces a human-readable summary with before/after context.
|
|
11
|
+
|
|
12
|
+
## Responsibilities
|
|
13
|
+
- Re-read each modified file and diff against the change log from `techdebt-fixer`
|
|
14
|
+
- Verify no unintended lines were altered (scope creep check)
|
|
15
|
+
- Confirm removed imports were genuinely unused by re-scanning usage in file body
|
|
16
|
+
- Check that removing a `console.log` did not break a surrounding `if` block structure
|
|
17
|
+
- Produce a formatted summary grouped by category for user confirmation
|
|
18
|
+
|
|
19
|
+
## Input
|
|
20
|
+
Change log JSON from `techdebt-fixer` plus current file content from Read tool.
|
|
21
|
+
|
|
22
|
+
## Output
|
|
23
|
+
Human-readable review report:
|
|
24
|
+
```markdown
|
|
25
|
+
## Techdebt Fix Review
|
|
26
|
+
|
|
27
|
+
### Ready to Apply (N changes)
|
|
28
|
+
- src/api/auth.ts:12 — removed console.log(token) [verified safe]
|
|
29
|
+
- src/components/Button.tsx:3 — removed unused React import [verified safe]
|
|
30
|
+
|
|
31
|
+
### Flagged for Manual Review (N items)
|
|
32
|
+
- src/services/user.ts:45 — any type, needs proper interface definition
|
|
33
|
+
|
|
34
|
+
All changes are reversible with git checkout.
|
|
35
|
+
```
|
|
36
|
+
Final confirmation prompt to user before any edits are committed.
|
|
37
|
+
|
|
38
|
+
## Communication
|
|
39
|
+
- Reports review summary to: orchestrator / user
|
|
40
|
+
- Receives instructions from: techdebt orchestrator (SKILL.md)
|
|
41
|
+
|
|
42
|
+
## Domain Knowledge
|
|
43
|
+
Verification checklist:
|
|
44
|
+
- Import removal: identifier must appear zero times outside the import line
|
|
45
|
+
- Console removal: surrounding block must remain syntactically valid
|
|
46
|
+
- Commented code removal: must not be a doc comment (`/** */`) or license header
|
|
47
|
+
- Scope rule: reviewer changes nothing — read-only gate only
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: techdebt-scanner
|
|
3
|
+
role: Scans codebase for code smells — any types, console.log, unused imports, magic numbers
|
|
4
|
+
tools: [Grep, Glob, Read]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Techdebt Scanner
|
|
8
|
+
|
|
9
|
+
## Role
|
|
10
|
+
Performs broad pattern-based scanning across the codebase to locate instances of known code smells. Produces a raw findings list with file paths and line numbers. Does not assess severity — that is the analyzer's job.
|
|
11
|
+
|
|
12
|
+
## Responsibilities
|
|
13
|
+
- Scan for `any` and `as any` TypeScript type violations
|
|
14
|
+
- Detect `console.log`, `console.error`, `console.warn`, `debugger` statements
|
|
15
|
+
- Find unused import statements by cross-referencing declaration vs. usage
|
|
16
|
+
- Locate magic numbers and hardcoded string literals outside constant files
|
|
17
|
+
- Detect commented-out code blocks containing code constructs
|
|
18
|
+
|
|
19
|
+
## Input
|
|
20
|
+
- Root directory path to scan
|
|
21
|
+
- Optional glob filter (e.g., `src/**/*.{ts,tsx}`)
|
|
22
|
+
- Optional category filter (e.g., scan only `any-types`)
|
|
23
|
+
|
|
24
|
+
## Output
|
|
25
|
+
Structured findings list in JSON format:
|
|
26
|
+
```json
|
|
27
|
+
[
|
|
28
|
+
{ "category": "any-type", "file": "src/services/user.ts", "line": 34, "snippet": ": any" },
|
|
29
|
+
{ "category": "console-log", "file": "src/api/auth.ts", "line": 12, "snippet": "console.log(token)" },
|
|
30
|
+
{ "category": "magic-number", "file": "src/utils/calc.ts", "line": 10, "snippet": "* 365" }
|
|
31
|
+
]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Communication
|
|
35
|
+
- Reports findings to: `techdebt-analyzer`
|
|
36
|
+
- Receives instructions from: techdebt orchestrator (SKILL.md)
|
|
37
|
+
|
|
38
|
+
## Domain Knowledge
|
|
39
|
+
Scan patterns:
|
|
40
|
+
- `any` types: `: any\b`, `as any\b`, `<any>`
|
|
41
|
+
- Debug code: `console\.(log|error|warn|debug|info)`, `\bdebugger\b`
|
|
42
|
+
- Magic numbers: numeric literals outside `const` declarations, ignoring 0, 1, -1, 100
|
|
43
|
+
- Commented code: `^\s*//.*\b(function|const|let|var|class|import)\b`
|
|
44
|
+
- Unused imports: declared in `import { X }` but `X` never referenced in file body
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: techdebt-orchestrator
|
|
3
|
+
type: orchestrator
|
|
4
|
+
agents: [scanner, analyzer, fixer, reviewer]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Techdebt Orchestrator
|
|
8
|
+
|
|
9
|
+
## Workflow
|
|
10
|
+
|
|
11
|
+
### Phase 1: Scan
|
|
12
|
+
- **Agent**: scanner
|
|
13
|
+
- **Input**: Changed file paths (or root dir + glob filter)
|
|
14
|
+
- **Output**: Raw findings list `[{category, file, line, snippet}]`
|
|
15
|
+
- **Parallel**: yes — each file scanned independently
|
|
16
|
+
|
|
17
|
+
### Phase 2: Analyze
|
|
18
|
+
- **Agent**: analyzer
|
|
19
|
+
- **Input**: Raw findings list from Phase 1
|
|
20
|
+
- **Output**: Scored findings with severity (P0–P3) and auto-fix eligibility flag
|
|
21
|
+
- **Parallel**: no — requires full findings set for deduplication
|
|
22
|
+
|
|
23
|
+
### Phase 3: Fix
|
|
24
|
+
- **Agent**: fixer
|
|
25
|
+
- **Input**: Findings flagged `auto-fixable: true` from Phase 2
|
|
26
|
+
- **Output**: Patch set (file edits) for each auto-fixable item
|
|
27
|
+
- **Parallel**: yes — patches per file are independent
|
|
28
|
+
|
|
29
|
+
### Phase 4: Review
|
|
30
|
+
- **Agent**: reviewer
|
|
31
|
+
- **Input**: Patch set from Phase 3
|
|
32
|
+
- **Output**: Approved patches + rejected patches with rejection reason
|
|
33
|
+
- **Parallel**: no — needs holistic view to catch patch conflicts
|
|
34
|
+
|
|
35
|
+
### Phase 5: Apply
|
|
36
|
+
- **Agent**: orchestrator (self)
|
|
37
|
+
- **Input**: Approved patches from Phase 4 + manual-review items from Phase 2
|
|
38
|
+
- **Output**: Applied fixes + final report with manual-review list
|
|
39
|
+
- **Parallel**: no — sequential file writes to avoid conflicts
|
|
40
|
+
|
|
41
|
+
## DAG (Dependency Graph)
|
|
42
|
+
|
|
43
|
+
```mermaid
|
|
44
|
+
graph TD
|
|
45
|
+
A[Phase 1: Scanner\nparallel per file] --> B[Phase 2: Analyzer]
|
|
46
|
+
B --> C[Phase 3: Fixer\nparallel per file]
|
|
47
|
+
B --> E[Manual Review Items]
|
|
48
|
+
C --> D[Phase 4: Reviewer]
|
|
49
|
+
D --> F[Phase 5: Apply]
|
|
50
|
+
E --> F
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Error Handling
|
|
54
|
+
|
|
55
|
+
| Phase | Failure Mode | Strategy |
|
|
56
|
+
|-------|-------------|----------|
|
|
57
|
+
| Phase 1 | File unreadable / binary file | Skip file, log warning, continue |
|
|
58
|
+
| Phase 1 | Glob returns 0 files | Escalate — prompt user to verify path |
|
|
59
|
+
| Phase 2 | Analyzer returns 0 findings | Skip phases 3–4, output clean report |
|
|
60
|
+
| Phase 3 | Patch generation fails for a file | Skip that file, flag for manual review |
|
|
61
|
+
| Phase 4 | Reviewer rejects all patches | Fallback to manual-review-only report |
|
|
62
|
+
| Phase 5 | Write conflict detected | Abort apply, show diff for manual resolution |
|
|
63
|
+
|
|
64
|
+
## Scalability Modes
|
|
65
|
+
|
|
66
|
+
| Mode | When | Agents Used |
|
|
67
|
+
|------|------|-------------|
|
|
68
|
+
| Full | Normal operation | scanner + analyzer + fixer + reviewer |
|
|
69
|
+
| Reduced | Time pressure / large repo | scanner + analyzer only (no auto-fix) |
|
|
70
|
+
| Single | Quick scan / pre-commit check | scanner only — raw findings, no scoring |
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Techdebt Severity Rubric
|
|
2
|
+
|
|
3
|
+
## P1 — Blocks Merge
|
|
4
|
+
|
|
5
|
+
Issues that introduce bugs, security holes, or break type safety. Must fix before merging.
|
|
6
|
+
|
|
7
|
+
| Pattern | Why P1 |
|
|
8
|
+
|---------|--------|
|
|
9
|
+
| `: any` / `as any` | Breaks TypeScript safety guarantee |
|
|
10
|
+
| `@ts-ignore` | Hides real type errors |
|
|
11
|
+
| `debugger` statement | Halts execution in production |
|
|
12
|
+
| Hardcoded secrets / credentials | Security risk |
|
|
13
|
+
| Circular imports causing runtime errors | Breaks module loading |
|
|
14
|
+
|
|
15
|
+
**Rule**: P1 count must be 0 before merge.
|
|
16
|
+
|
|
17
|
+
## P2 — Fix Before PR
|
|
18
|
+
|
|
19
|
+
Issues that reduce maintainability, performance, or correctness. Should be resolved before PR review.
|
|
20
|
+
|
|
21
|
+
| Pattern | Why P2 |
|
|
22
|
+
|---------|--------|
|
|
23
|
+
| `console.log` / `console.warn` | Debug noise in production logs |
|
|
24
|
+
| Functions > 50 lines | Violates complexity limit; hard to test |
|
|
25
|
+
| Nesting depth > 4 | Cognitive overload; obscures logic |
|
|
26
|
+
| Unused imports | Bundle bloat; misleading code |
|
|
27
|
+
| TODO/FIXME without ticket | Ambiguous ownership |
|
|
28
|
+
| Duplicate logic (2+ files) | Maintenance hazard |
|
|
29
|
+
|
|
30
|
+
**Rule**: P2 items are warnings. Resolve or create a tracked P3 ticket before merge.
|
|
31
|
+
|
|
32
|
+
## P3 — Backlog
|
|
33
|
+
|
|
34
|
+
Issues that are cosmetic or nice-to-have. Address during scheduled cleanup sessions.
|
|
35
|
+
|
|
36
|
+
| Pattern | Why P3 |
|
|
37
|
+
|---------|--------|
|
|
38
|
+
| Magic numbers (non-critical) | Readability |
|
|
39
|
+
| Commented-out code | Noise |
|
|
40
|
+
| Inconsistent naming | Style drift |
|
|
41
|
+
| Missing JSDoc on internal helpers | Documentation gap |
|
|
42
|
+
| Slightly long files (200–499 lines) | Future extraction candidate |
|
|
43
|
+
|
|
44
|
+
**Rule**: P3 items never block. Review weekly; archive when resolved.
|
|
45
|
+
|
|
46
|
+
## Convergence Rule
|
|
47
|
+
|
|
48
|
+
- Round 1: address all P1 + P2
|
|
49
|
+
- Round 2: address remaining P1 + P2 only
|
|
50
|
+
- Round 3+: P1 only
|
|
51
|
+
- Same findings as previous round → stop immediately
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* techdebt/scripts/scan.js
|
|
4
|
+
* Scan a directory for technical debt patterns.
|
|
5
|
+
* Usage: node scan.js <directory>
|
|
6
|
+
* Output: JSON array of findings to stdout.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
|
|
12
|
+
const TARGET_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx']);
|
|
13
|
+
|
|
14
|
+
/** @returns {string[]} */
|
|
15
|
+
function collectFiles(dir) {
|
|
16
|
+
const results = [];
|
|
17
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
18
|
+
if (entry.name.startsWith('.') || entry.name === 'node_modules' || entry.name === 'dist') continue;
|
|
19
|
+
const full = path.join(dir, entry.name);
|
|
20
|
+
if (entry.isDirectory()) results.push(...collectFiles(full));
|
|
21
|
+
else if (TARGET_EXTENSIONS.has(path.extname(entry.name))) results.push(full);
|
|
22
|
+
}
|
|
23
|
+
return results;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** @param {string} file @returns {import('./scan.js').Finding[]} */
|
|
27
|
+
function scanFile(file) {
|
|
28
|
+
const lines = fs.readFileSync(file, 'utf-8').split('\n');
|
|
29
|
+
const findings = [];
|
|
30
|
+
let functionLineStart = -1;
|
|
31
|
+
let braceDepth = 0;
|
|
32
|
+
let functionLineCount = 0;
|
|
33
|
+
let maxNesting = 0;
|
|
34
|
+
let currentNesting = 0;
|
|
35
|
+
|
|
36
|
+
const push = (line, type, severity, message) =>
|
|
37
|
+
findings.push({ file, line: line + 1, type, severity, message });
|
|
38
|
+
|
|
39
|
+
for (let i = 0; i < lines.length; i++) {
|
|
40
|
+
const raw = lines[i];
|
|
41
|
+
const trimmed = raw.trim();
|
|
42
|
+
|
|
43
|
+
if (/:\s*any\b|as\s+any\b/.test(trimmed)) push(i, 'any-type', 'P1', `'any' type usage detected`);
|
|
44
|
+
if (/console\.(log|warn|error|debug)\s*\(/.test(trimmed)) push(i, 'console-log', 'P2', `console statement found`);
|
|
45
|
+
if (/^import\s+/.test(trimmed)) {
|
|
46
|
+
const match = trimmed.match(/^import\s+\{([^}]+)\}/);
|
|
47
|
+
if (match) {
|
|
48
|
+
const names = match[1].split(',').map(n => n.trim().split(/\s+as\s+/).pop());
|
|
49
|
+
for (const name of names) {
|
|
50
|
+
const usedElsewhere = lines.slice(i + 1).some(l => new RegExp(`\\b${name}\\b`).test(l));
|
|
51
|
+
if (!usedElsewhere) push(i, 'unused-import', 'P2', `Possibly unused import: ${name}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const magicNumber = trimmed.match(/(?<![A-Za-z_$'"`])\b([2-9]\d{2,}|\d{4,})\b(?![A-Za-z_$'"`])/);
|
|
56
|
+
if (magicNumber && !/^\s*(\/\/|\/\*)/.test(raw)) push(i, 'magic-number', 'P3', `Magic number: ${magicNumber[1]}`);
|
|
57
|
+
|
|
58
|
+
const opens = (raw.match(/\{/g) || []).length;
|
|
59
|
+
const closes = (raw.match(/\}/g) || []).length;
|
|
60
|
+
if (/\bfunction\b|\=\>/.test(raw) && opens > closes) {
|
|
61
|
+
functionLineStart = i;
|
|
62
|
+
functionLineCount = 0;
|
|
63
|
+
braceDepth = opens - closes;
|
|
64
|
+
} else if (functionLineStart >= 0) {
|
|
65
|
+
braceDepth += opens - closes;
|
|
66
|
+
functionLineCount++;
|
|
67
|
+
if (braceDepth <= 0) {
|
|
68
|
+
if (functionLineCount > 50) push(functionLineStart, 'long-function', 'P2', `Function is ${functionLineCount} lines (limit: 50)`);
|
|
69
|
+
functionLineStart = -1;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const indent = raw.match(/^(\s*)/)[1].length;
|
|
74
|
+
currentNesting = Math.floor(indent / 2);
|
|
75
|
+
if (currentNesting > maxNesting) maxNesting = currentNesting;
|
|
76
|
+
if (currentNesting > 4) push(i, 'deep-nesting', 'P2', `Nesting depth ${currentNesting} exceeds limit of 4`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return findings;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const dir = process.argv[2] || process.cwd();
|
|
83
|
+
if (!fs.existsSync(dir)) {
|
|
84
|
+
process.stderr.write(`Directory not found: ${dir}\n`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const files = collectFiles(path.resolve(dir));
|
|
89
|
+
const findings = files.flatMap(scanFile);
|
|
90
|
+
process.stdout.write(JSON.stringify(findings, null, 2) + '\n');
|