@dinyangetoh/codeplug-cli 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +286 -45
- package/dist/cli/commands/convention.d.ts +1 -1
- package/dist/cli/commands/convention.d.ts.map +1 -1
- package/dist/cli/commands/convention.js +174 -31
- package/dist/cli/commands/convention.js.map +1 -1
- package/dist/cli/commands/docs.d.ts +3 -1
- package/dist/cli/commands/docs.d.ts.map +1 -1
- package/dist/cli/commands/docs.js +13 -2
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/export.d.ts.map +1 -1
- package/dist/cli/commands/export.js +6 -1
- package/dist/cli/commands/export.js.map +1 -1
- package/dist/cli/commands/start.d.ts +2 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +172 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/index.js +10 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/config/ConfigManager.d.ts +18 -0
- package/dist/config/ConfigManager.d.ts.map +1 -1
- package/dist/config/ConfigManager.js +55 -2
- package/dist/config/ConfigManager.js.map +1 -1
- package/dist/config/ConventionSchema.d.ts +59 -0
- package/dist/config/ConventionSchema.d.ts.map +1 -1
- package/dist/config/ConventionSchema.js +11 -0
- package/dist/config/ConventionSchema.js.map +1 -1
- package/dist/config/defaults.d.ts +60 -2
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +136 -20
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/types.d.ts +71 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/core/analyzer/AstAnalyzer.d.ts +11 -2
- package/dist/core/analyzer/AstAnalyzer.d.ts.map +1 -1
- package/dist/core/analyzer/AstAnalyzer.js +21 -5
- package/dist/core/analyzer/AstAnalyzer.js.map +1 -1
- package/dist/core/analyzer/ConventionDetector.d.ts +12 -1
- package/dist/core/analyzer/ConventionDetector.d.ts.map +1 -1
- package/dist/core/analyzer/ConventionDetector.js +120 -20
- package/dist/core/analyzer/ConventionDetector.js.map +1 -1
- package/dist/core/analyzer/ConventionMlResolver.d.ts +4 -0
- package/dist/core/analyzer/ConventionMlResolver.d.ts.map +1 -0
- package/dist/core/analyzer/ConventionMlResolver.js +17 -0
- package/dist/core/analyzer/ConventionMlResolver.js.map +1 -0
- package/dist/core/analyzer/PatternAggregator.d.ts +11 -2
- package/dist/core/analyzer/PatternAggregator.d.ts.map +1 -1
- package/dist/core/analyzer/PatternAggregator.js +87 -15
- package/dist/core/analyzer/PatternAggregator.js.map +1 -1
- package/dist/core/analyzer/SemanticCoherencePhase.d.ts +10 -0
- package/dist/core/analyzer/SemanticCoherencePhase.d.ts.map +1 -0
- package/dist/core/analyzer/SemanticCoherencePhase.js +191 -0
- package/dist/core/analyzer/SemanticCoherencePhase.js.map +1 -0
- package/dist/core/analyzer/SemanticCoherenceService.d.ts +11 -0
- package/dist/core/analyzer/SemanticCoherenceService.d.ts.map +1 -0
- package/dist/core/analyzer/SemanticCoherenceService.js +56 -0
- package/dist/core/analyzer/SemanticCoherenceService.js.map +1 -0
- package/dist/core/analyzer/visitors/ComponentVisitor.d.ts.map +1 -1
- package/dist/core/analyzer/visitors/ComponentVisitor.js +2 -2
- package/dist/core/analyzer/visitors/ComponentVisitor.js.map +1 -1
- package/dist/core/analyzer/visitors/ErrorHandlingVisitor.d.ts.map +1 -1
- package/dist/core/analyzer/visitors/ErrorHandlingVisitor.js +2 -2
- package/dist/core/analyzer/visitors/ErrorHandlingVisitor.js.map +1 -1
- package/dist/core/analyzer/visitors/ImportVisitor.d.ts +5 -0
- package/dist/core/analyzer/visitors/ImportVisitor.d.ts.map +1 -1
- package/dist/core/analyzer/visitors/ImportVisitor.js +8 -3
- package/dist/core/analyzer/visitors/ImportVisitor.js.map +1 -1
- package/dist/core/analyzer/visitors/NamingVisitor.d.ts +20 -2
- package/dist/core/analyzer/visitors/NamingVisitor.d.ts.map +1 -1
- package/dist/core/analyzer/visitors/NamingVisitor.js +464 -25
- package/dist/core/analyzer/visitors/NamingVisitor.js.map +1 -1
- package/dist/core/analyzer/visitors/SchemaVisitor.d.ts +7 -0
- package/dist/core/analyzer/visitors/SchemaVisitor.d.ts.map +1 -0
- package/dist/core/analyzer/visitors/SchemaVisitor.js +50 -0
- package/dist/core/analyzer/visitors/SchemaVisitor.js.map +1 -0
- package/dist/core/analyzer/visitors/StructureVisitor.d.ts +4 -1
- package/dist/core/analyzer/visitors/StructureVisitor.d.ts.map +1 -1
- package/dist/core/analyzer/visitors/StructureVisitor.js +38 -4
- package/dist/core/analyzer/visitors/StructureVisitor.js.map +1 -1
- package/dist/core/analyzer/visitors/types.d.ts +4 -0
- package/dist/core/analyzer/visitors/types.d.ts.map +1 -1
- package/dist/core/classifier/CodeBertEmbedder.d.ts +9 -0
- package/dist/core/classifier/CodeBertEmbedder.d.ts.map +1 -0
- package/dist/core/classifier/CodeBertEmbedder.js +33 -0
- package/dist/core/classifier/CodeBertEmbedder.js.map +1 -0
- package/dist/core/classifier/ConfidenceGate.d.ts +2 -0
- package/dist/core/classifier/ConfidenceGate.d.ts.map +1 -1
- package/dist/core/classifier/ConfidenceGate.js +6 -2
- package/dist/core/classifier/ConfidenceGate.js.map +1 -1
- package/dist/core/exporter/FreshnessChecker.d.ts +5 -1
- package/dist/core/exporter/FreshnessChecker.d.ts.map +1 -1
- package/dist/core/exporter/FreshnessChecker.js +5 -10
- package/dist/core/exporter/FreshnessChecker.js.map +1 -1
- package/dist/core/generator/DocGenerator.d.ts +6 -1
- package/dist/core/generator/DocGenerator.d.ts.map +1 -1
- package/dist/core/generator/DocGenerator.js +62 -7
- package/dist/core/generator/DocGenerator.js.map +1 -1
- package/dist/core/generator/StalenessTracker.d.ts +7 -1
- package/dist/core/generator/StalenessTracker.d.ts.map +1 -1
- package/dist/core/generator/StalenessTracker.js +12 -12
- package/dist/core/generator/StalenessTracker.js.map +1 -1
- package/dist/core/generator/documents/ArchitectureGenerator.d.ts +1 -0
- package/dist/core/generator/documents/ArchitectureGenerator.d.ts.map +1 -1
- package/dist/core/generator/documents/ArchitectureGenerator.js +37 -12
- package/dist/core/generator/documents/ArchitectureGenerator.js.map +1 -1
- package/dist/core/generator/documents/ContributingGenerator.d.ts.map +1 -1
- package/dist/core/generator/documents/ContributingGenerator.js +20 -13
- package/dist/core/generator/documents/ContributingGenerator.js.map +1 -1
- package/dist/core/generator/documents/ConventionsGenerator.d.ts.map +1 -1
- package/dist/core/generator/documents/ConventionsGenerator.js +16 -2
- package/dist/core/generator/documents/ConventionsGenerator.js.map +1 -1
- package/dist/core/generator/documents/OnboardingGenerator.d.ts.map +1 -1
- package/dist/core/generator/documents/OnboardingGenerator.js +26 -18
- package/dist/core/generator/documents/OnboardingGenerator.js.map +1 -1
- package/dist/core/generator/documents/ReadmeGenerator.d.ts.map +1 -1
- package/dist/core/generator/documents/ReadmeGenerator.js +26 -14
- package/dist/core/generator/documents/ReadmeGenerator.js.map +1 -1
- package/dist/core/generator/documents/types.d.ts +8 -1
- package/dist/core/generator/documents/types.d.ts.map +1 -1
- package/dist/core/generator/mlPipelineBuilder.d.ts +8 -0
- package/dist/core/generator/mlPipelineBuilder.d.ts.map +1 -0
- package/dist/core/generator/mlPipelineBuilder.js +117 -0
- package/dist/core/generator/mlPipelineBuilder.js.map +1 -0
- package/dist/core/scorer/ComplianceScorer.d.ts +5 -1
- package/dist/core/scorer/ComplianceScorer.d.ts.map +1 -1
- package/dist/core/scorer/ComplianceScorer.js +47 -23
- package/dist/core/scorer/ComplianceScorer.js.map +1 -1
- package/dist/core/scorer/ViolationDetector.d.ts +19 -2
- package/dist/core/scorer/ViolationDetector.d.ts.map +1 -1
- package/dist/core/scorer/ViolationDetector.js +169 -53
- package/dist/core/scorer/ViolationDetector.js.map +1 -1
- package/dist/models/ModelManager.d.ts +5 -1
- package/dist/models/ModelManager.d.ts.map +1 -1
- package/dist/models/ModelManager.js +19 -5
- package/dist/models/ModelManager.js.map +1 -1
- package/dist/models/ModelRegistry.d.ts +1 -1
- package/dist/models/ModelRegistry.d.ts.map +1 -1
- package/dist/models/ModelRegistry.js +28 -0
- package/dist/models/ModelRegistry.js.map +1 -1
- package/dist/storage/CustomRuleStore.d.ts +9 -0
- package/dist/storage/CustomRuleStore.d.ts.map +1 -0
- package/dist/storage/CustomRuleStore.js +22 -0
- package/dist/storage/CustomRuleStore.js.map +1 -0
- package/dist/storage/ScoreStore.d.ts +2 -5
- package/dist/storage/ScoreStore.d.ts.map +1 -1
- package/dist/storage/ScoreStore.js +23 -71
- package/dist/storage/ScoreStore.js.map +1 -1
- package/package.json +4 -3
- package/dist/core/classifier/DriftClassifier.d.ts +0 -17
- package/dist/core/classifier/DriftClassifier.d.ts.map +0 -1
- package/dist/core/classifier/DriftClassifier.js +0 -293
- package/dist/core/classifier/DriftClassifier.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,55 +1,75 @@
|
|
|
1
1
|
# CodePlug
|
|
2
2
|
|
|
3
|
+
## Executive Summary
|
|
4
|
+
|
|
5
|
+
This document provides comprehensive technical documentation for CodePlug, a local-first CLI tool designed to detect, enforce, and document coding conventions across TypeScript/JavaScript codebases. The guide covers installation, configuration, usage commands, project architecture, and development workflows for teams seeking automated codebase governance with AI agent integration capabilities.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
3
11
|
**The source of truth for codebase understanding and governance.**
|
|
4
12
|
|
|
5
13
|
CodePlug is a local-first CLI tool that detects your codebase's coding conventions, enforces them with drift detection and compliance scoring, generates living documentation, and exports convention context for AI coding agents.
|
|
6
14
|
|
|
15
|
+
The tool operates entirely on-device using ML models for pattern detection, ensuring your codebase data never leaves your machine unless you explicitly configure cloud LLM providers for enhanced documentation generation.
|
|
16
|
+
|
|
7
17
|
---
|
|
8
18
|
|
|
9
|
-
## Features
|
|
19
|
+
## Key Features
|
|
10
20
|
|
|
11
|
-
|
|
12
|
-
- **Drift & Compliance** -- Classifies git diffs against stored conventions, scores compliance with severity-weighted metrics, tracks trends over time, and auto-fixes what it can.
|
|
13
|
-
- **Living Documentation** -- Generates and maintains README, ARCHITECTURE, CONVENTIONS, CONTRIBUTING, and ONBOARDING docs using ML summarization and optional LLM enhancement.
|
|
14
|
-
- **AI Agent Export** -- Exports your conventions as `CLAUDE.md`, `.cursor/rules`, `.github/copilot-instructions.md`, structured JSON, and SARIF-format CI reports.
|
|
21
|
+
### Convention Detection
|
|
15
22
|
|
|
16
|
-
|
|
23
|
+
AST analysis with on-device ML identifies naming patterns, folder structure, component styles, test organization, error handling, and import conventions across your TypeScript/JavaScript codebase.
|
|
17
24
|
|
|
18
|
-
|
|
25
|
+
### Drift & Compliance
|
|
19
26
|
|
|
20
|
-
|
|
21
|
-
# Install globally
|
|
22
|
-
npm install -g @dinyangetoh/codeplug-cli
|
|
27
|
+
Classifies git diffs against stored conventions, scores compliance with severity-weighted metrics, tracks trends over time, and auto-fixes what it can.
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
cd your-project
|
|
29
|
+
### Living Documentation
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
codeplug convention init
|
|
31
|
+
Generates and maintains README, ARCHITECTURE, CONVENTIONS, CONTRIBUTING, and ONBOARDING docs using ML summarization and optional LLM enhancement.
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
### AI Agent Export
|
|
34
|
+
|
|
35
|
+
Exports your conventions as `CLAUDE.md`, `.cursor/rules`, `.github/copilot-instructions.md`, structured JSON, and SARIF-format CI reports.
|
|
36
|
+
|
|
37
|
+
### All Features
|
|
38
|
+
|
|
39
|
+
| Category | Feature | Command / Config | Notes |
|
|
40
|
+
|----------|---------|------------------|-------|
|
|
41
|
+
| CLI | Interactive wizard | `codeplug start` | Config, Convention, Docs, Export menus; see [COMMAND.md](COMMAND.md) |
|
|
42
|
+
| Convention | Detection (6 dimensions) | `convention init` | Naming, Component, Test, ErrorHandling, Import, Schema visitors |
|
|
43
|
+
| Convention | Structure (7th dimension) | `convention audit` | StructureVisitor in ViolationDetector |
|
|
44
|
+
| Convention | Drift | `convention drift` | Rule-based diff classification |
|
|
45
|
+
| Convention | Compliance | `convention audit`, `score` | Severity-weighted, sql.js time-series |
|
|
46
|
+
| Convention | Auto-fix | `convention fix` | Rename + manual guidance |
|
|
47
|
+
| Convention | Semantic coherence | `convention.enableSemanticCoherence` | Opt-in; zero-shot + sentenceSimilarity |
|
|
48
|
+
| Convention | Custom rules | `.codeplug/rules.json` | Regex rules (filename, path, content) |
|
|
49
|
+
| Docs | Generate / Status / Update | `docs generate/status/update` | 5 docs, ML pipeline + optional LLM; template fallback |
|
|
50
|
+
| Export | Claude / Cursor / Copilot | `export --target` | CLAUDE.md, .cursor/rules, .github/copilot-instructions |
|
|
51
|
+
| Export | JSON / CI (SARIF) | `export --target json/ci` | .codeplug/exports/, .codeplug/ci-report.json |
|
|
52
|
+
| Config | Model tier, LLM provider | `config set` | default / lite; 8 providers |
|
|
33
53
|
|
|
34
54
|
---
|
|
35
55
|
|
|
36
56
|
## Prerequisites
|
|
37
57
|
|
|
38
|
-
- **Node.js 20+** (required)
|
|
39
|
-
- **Git** (required for drift detection and history analysis)
|
|
40
|
-
- **Ollama** (optional
|
|
58
|
+
- **Node.js 20+** (required) — CodePlug is built with TypeScript and requires Node.js 20 or higher for native fetch and modern ESM support.
|
|
59
|
+
- **Git** (required for drift detection and history analysis) — CodePlug integrates with Git for diff analysis, commit history inspection, and pre-commit hook management.
|
|
60
|
+
- **Ollama** (optional) — For LLM-enhanced documentation. Any OpenAI-compatible provider works as an alternative.
|
|
41
61
|
|
|
42
62
|
---
|
|
43
63
|
|
|
44
64
|
## Installation
|
|
45
65
|
|
|
46
|
-
### Global
|
|
66
|
+
### Global Install
|
|
47
67
|
|
|
48
68
|
```bash
|
|
49
69
|
npm install -g @dinyangetoh/codeplug-cli
|
|
50
70
|
```
|
|
51
71
|
|
|
52
|
-
### Local
|
|
72
|
+
### Local Development
|
|
53
73
|
|
|
54
74
|
```bash
|
|
55
75
|
git clone <repo-url>
|
|
@@ -61,8 +81,50 @@ node dist/cli/index.js --help
|
|
|
61
81
|
|
|
62
82
|
---
|
|
63
83
|
|
|
84
|
+
## Quick Start
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Install globally
|
|
88
|
+
npm install -g @dinyangetoh/codeplug-cli
|
|
89
|
+
|
|
90
|
+
# Navigate to your project
|
|
91
|
+
cd your-project
|
|
92
|
+
|
|
93
|
+
# Interactive wizard — single entry point for new users
|
|
94
|
+
codeplug start
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Or run commands directly:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Detect and confirm conventions
|
|
101
|
+
codeplug convention init
|
|
102
|
+
|
|
103
|
+
# Check compliance
|
|
104
|
+
codeplug convention audit
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
64
109
|
## Usage
|
|
65
110
|
|
|
111
|
+
### Interactive Wizard
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
codeplug start
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Launches an interactive menu with four core areas:
|
|
118
|
+
|
|
119
|
+
| Menu | Options |
|
|
120
|
+
| -------- | ----------------------------------------------------------------------- |
|
|
121
|
+
| Config | View full config, Set provider/model/API key/tier, Back |
|
|
122
|
+
| Convention | Initialize, Run audit, Check drift, Show score, Auto-fix, Back |
|
|
123
|
+
| Docs | Generate docs, Check status, Update stale, Back |
|
|
124
|
+
| Export | Export all targets, Check freshness, Back |
|
|
125
|
+
|
|
126
|
+
Use arrow keys to navigate and Enter to select. Each sub-menu has a Back option to return.
|
|
127
|
+
|
|
66
128
|
### Convention Detection
|
|
67
129
|
|
|
68
130
|
```bash
|
|
@@ -162,6 +224,12 @@ codeplug config set llm.model gpt-4o
|
|
|
162
224
|
codeplug config set llm.apiKey sk-...
|
|
163
225
|
```
|
|
164
226
|
|
|
227
|
+
### Planned / Partial Features
|
|
228
|
+
|
|
229
|
+
- **`convention show <commit>`**: Listed in help; returns "Not yet implemented. Coming in Phase 2."
|
|
230
|
+
- **Pre-commit hook**: PreCommitHook class exists; `codeplug hook install/uninstall` commands are not yet exposed (programmatic API; coming soon).
|
|
231
|
+
- **Export `--target ci`**: Produces SARIF 2.1.0 at `.codeplug/ci-report.json` for CI integration.
|
|
232
|
+
|
|
165
233
|
---
|
|
166
234
|
|
|
167
235
|
## Configuration
|
|
@@ -198,6 +266,56 @@ codeplug config set models.tier lite
|
|
|
198
266
|
|
|
199
267
|
Switching to `lite` prints a warning about potential quality degradation.
|
|
200
268
|
|
|
269
|
+
### Configurable Sections
|
|
270
|
+
|
|
271
|
+
CodePlug supports optional sections in `.codeplug/config.json`. Each section merges with built-in defaults (shallow merge). Omit a section to keep defaults.
|
|
272
|
+
|
|
273
|
+
```mermaid
|
|
274
|
+
flowchart TB
|
|
275
|
+
subgraph sources [Config Sources]
|
|
276
|
+
Defaults[DEFAULT_CONFIG]
|
|
277
|
+
User[config.json]
|
|
278
|
+
end
|
|
279
|
+
Defaults --> Merge[ConfigManager.load]
|
|
280
|
+
User --> Merge
|
|
281
|
+
Merge --> Config[CodePlugConfig]
|
|
282
|
+
Config --> Structure[structure]
|
|
283
|
+
Config --> Analysis[analysis]
|
|
284
|
+
Config --> Scoring[scoring]
|
|
285
|
+
Config --> Convention[convention]
|
|
286
|
+
Config --> Drift[drift]
|
|
287
|
+
Config --> Docs[docs]
|
|
288
|
+
Config --> Naming[naming]
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
| Section | Purpose |
|
|
292
|
+
|---------|---------|
|
|
293
|
+
| `structure` | Architecture patterns (feature-based, MVC, layered) and directory placement rules (e.g. *Helper in helpers/) |
|
|
294
|
+
| `analysis` | Glob `include` and `ignore` for file discovery |
|
|
295
|
+
| `scoring` | Severity weights, compliance threshold, trend window |
|
|
296
|
+
| `convention` | Confidence threshold and dimension → severity map |
|
|
297
|
+
| `drift` | Confidence threshold and naming pattern regexes |
|
|
298
|
+
| `docs` | Tracked doc names, export targets, dev scripts |
|
|
299
|
+
| `naming` | Stem stopwords for file-responsibility extraction |
|
|
300
|
+
|
|
301
|
+
### Custom Rules
|
|
302
|
+
|
|
303
|
+
Add regex-based rules via `.codeplug/rules.json`. Schema: `id`, `pattern`, `scope` (filename | path | content), `message`, `severity` (optional).
|
|
304
|
+
|
|
305
|
+
```json
|
|
306
|
+
[{ "id": "no-index-export", "pattern": "export \\* from", "scope": "content", "message": "Prefer named exports", "severity": "low" }]
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Data Files
|
|
310
|
+
|
|
311
|
+
| File | Purpose |
|
|
312
|
+
|------|---------|
|
|
313
|
+
| `.codeplug/config.json` | Project config (LLM, models, analysis, etc.) |
|
|
314
|
+
| `.codeplug/conventions.json` | Stored conventions from `convention init` |
|
|
315
|
+
| `.codeplug/rules.json` | Custom regex rules for audit |
|
|
316
|
+
| `.codeplug/scores.json` | Compliance score history (sql.js) |
|
|
317
|
+
| `.codeplug/violations.json` | Recent violation records |
|
|
318
|
+
|
|
201
319
|
---
|
|
202
320
|
|
|
203
321
|
## Supported LLM Providers
|
|
@@ -222,14 +340,158 @@ All providers work through a single unified client via the OpenAI SDK.
|
|
|
222
340
|
| | Default | Lite |
|
|
223
341
|
|---|---------|------|
|
|
224
342
|
| Target machine | 8GB+ RAM | 4GB+ RAM |
|
|
225
|
-
| Disk usage | ~1.
|
|
343
|
+
| Disk usage | ~1.2GB | ~450MB |
|
|
226
344
|
| Classification | CodeBERT-base (125M params) | CodeBERTa-small (84M params) |
|
|
227
345
|
| Summarization | BART-large-CNN (406M params) | DistilBART (230M params) |
|
|
228
346
|
| NER | BERT-base-NER (110M params) | DistilBERT-NER (66M params) |
|
|
347
|
+
| Zero-shot | DistilBERT-MNLI (68MB) | DistilBERT-MNLI (68MB) |
|
|
348
|
+
| Sentence similarity | all-MiniLM-L6-v2 (23MB) | all-MiniLM-L6-v2 (23MB) |
|
|
229
349
|
| When to use | Production quality, CI pipelines | Local development on constrained hardware |
|
|
230
350
|
|
|
351
|
+
**Model usage (all 6 roles used):**
|
|
352
|
+
|
|
353
|
+
| Role | Default | Lite | Used By |
|
|
354
|
+
|------|---------|------|---------|
|
|
355
|
+
| classifier | CodeBERT-base | CodeBERTa-small | ConventionMlResolver (convention init) |
|
|
356
|
+
| zeroShot | DistilBERT-MNLI | same | SemanticCoherenceService (opt-in) |
|
|
357
|
+
| sentenceSimilarity | all-MiniLM-L6-v2 | same | SemanticCoherenceService (fallback) |
|
|
358
|
+
| summarizer | BART-large-CNN | DistilBART | DocGenerator (docs generate) |
|
|
359
|
+
| extractor | DistilBERT-SQuAD | same | DocGenerator |
|
|
360
|
+
| ner | BERT-base-NER | DistilBERT-NER | DocGenerator |
|
|
361
|
+
|
|
362
|
+
Convention detection: AST visitors + CodeBERT (ConventionMlResolver) + zero-shot/sentenceSimilarity when semantic coherence enabled. Doc generation: summarizer, extractor, ner via PipelineOrchestrator (default); falls back to template-only on model load failure.
|
|
363
|
+
|
|
231
364
|
Models are downloaded on first use and cached in `~/.codeplug/models/`.
|
|
232
365
|
|
|
366
|
+
### Tradeoffs
|
|
367
|
+
|
|
368
|
+
- **Default vs Lite**: Quality vs resource usage (8GB vs 4GB RAM; ~1.2GB vs ~450MB disk).
|
|
369
|
+
- **Semantic coherence**: Enable for stricter "export fits context" checks; adds ~68MB model load and inference time per audit.
|
|
370
|
+
- **LLM for docs**: Optional; template-only fallback when LLM unavailable.
|
|
371
|
+
- **Performance targets**: CLI startup <1s; init ~500 files <15s; drift <3s; audit <30s; docs (all 5) <2min.
|
|
372
|
+
|
|
373
|
+
### Hugging Face Transformers
|
|
374
|
+
|
|
375
|
+
Convention detection, drift, and compliance use **on-device ML only** via `@huggingface/transformers`. No API keys or network calls for convention features.
|
|
376
|
+
|
|
377
|
+
**Why Transformers / Local-First ML**
|
|
378
|
+
|
|
379
|
+
```mermaid
|
|
380
|
+
flowchart LR
|
|
381
|
+
subgraph design [Design Rationale]
|
|
382
|
+
A[Privacy: no data leaves machine]
|
|
383
|
+
B[Zero cost for convention features]
|
|
384
|
+
C[Python-free Node.js inference]
|
|
385
|
+
D[Deterministic logic first ML fallback]
|
|
386
|
+
end
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
- **Privacy**: Convention detection, drift, compliance run entirely on-device — no API keys, no network calls.
|
|
390
|
+
- **Cost**: Zero runtime cost; models cached in `~/.codeplug/models/`.
|
|
391
|
+
- **Portability**: `@huggingface/transformers` runs in Node.js — no Python, no separate ML server.
|
|
392
|
+
- **Explainability**: Rule-based detection first; ML used for ambiguous cases (e.g., semantic coherence) to keep outputs explainable.
|
|
393
|
+
|
|
394
|
+
**Feature → Model usage:**
|
|
395
|
+
|
|
396
|
+
```mermaid
|
|
397
|
+
flowchart TB
|
|
398
|
+
subgraph convention [Convention Features]
|
|
399
|
+
Init[convention init]
|
|
400
|
+
Audit[convention audit]
|
|
401
|
+
end
|
|
402
|
+
subgraph conventionML [Convention ML]
|
|
403
|
+
CodeBERT[classifier: CodeBERT]
|
|
404
|
+
ZeroShot[zeroShot: DistilBERT-MNLI]
|
|
405
|
+
SentSim[sentenceSimilarity: all-MiniLM]
|
|
406
|
+
end
|
|
407
|
+
subgraph docsML [Docs ML]
|
|
408
|
+
BART[summarizer]
|
|
409
|
+
Extractor[extractor]
|
|
410
|
+
NER[ner]
|
|
411
|
+
end
|
|
412
|
+
Init --> CodeBERT
|
|
413
|
+
Init --> ZeroShot
|
|
414
|
+
Init --> SentSim
|
|
415
|
+
Audit --> conventionML
|
|
416
|
+
DocsGenerate[docs generate] --> BART
|
|
417
|
+
DocsGenerate --> Extractor
|
|
418
|
+
DocsGenerate --> NER
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
**Pipelines by feature:**
|
|
422
|
+
|
|
423
|
+
| Feature | Pipeline | Use |
|
|
424
|
+
|---------|----------|-----|
|
|
425
|
+
| Convention discovery | Feature extraction (CodeBERT embedding via ConventionMlResolver) | Pattern similarity during init |
|
|
426
|
+
| Convention (opt-in) | Zero-shot, sentence similarity (all-MiniLM) | Semantic coherence: "export fits file context" |
|
|
427
|
+
| Doc generation | Summarization (BART), Q&A (DistilBERT-SQuAD), NER (BERT-NER) | Living documentation; template fallback on load failure |
|
|
428
|
+
|
|
429
|
+
**LLM scope:** The LLM is **optional** and used only for prose generation in docs. Convention detection, drift, and compliance do not use an LLM.
|
|
430
|
+
|
|
431
|
+
**Cost:** Zero runtime cost for convention features; models are cached locally.
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## Project Structure
|
|
436
|
+
|
|
437
|
+
```
|
|
438
|
+
src/
|
|
439
|
+
├── cli/
|
|
440
|
+
│ └── commands/ # Command handlers (convention, docs, export, config)
|
|
441
|
+
├── config/ # ConfigManager, Zod schemas, types, provider presets
|
|
442
|
+
├── core/
|
|
443
|
+
│ ├── analyzer/ # AST analysis: 6 visitors (init), 7 for audit (adds StructureVisitor), PatternAggregator
|
|
444
|
+
│ ├── classifier/ # Drift classification + confidence gating
|
|
445
|
+
│ ├── scorer/ # Compliance scoring, violation detection, auto-fix, trends
|
|
446
|
+
│ ├── generator/ # Doc generation, ML pipelines, LLM client, staleness tracking
|
|
447
|
+
│ ├── exporter/ # Export engine + 5 formatters (Claude, Cursor, Copilot, JSON, CI)
|
|
448
|
+
│ └── git/ # Git integration + pre-commit hook management
|
|
449
|
+
├── models/ # ML model manager + tier-aware registry
|
|
450
|
+
├── storage/ # ConventionStore, ScoreStore (sql.js), ViolationStore, CustomRuleStore
|
|
451
|
+
├── templates/ # Export templates (Claude, Cursor, Copilot)
|
|
452
|
+
└── tests/ # Unit tests, integration tests, fixture repos
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Directory Details
|
|
456
|
+
|
|
457
|
+
| Directory | Purpose |
|
|
458
|
+
|-----------|---------|
|
|
459
|
+
| `cli/commands/` | Command handlers for the CLI interface |
|
|
460
|
+
| `config/` | Configuration management with Zod validation |
|
|
461
|
+
| `core/analyzer/` | AST-based code analysis with pattern aggregation |
|
|
462
|
+
| `core/classifier/` | Drift detection and severity classification |
|
|
463
|
+
| `core/scorer/` | Compliance scoring engine with trend analysis |
|
|
464
|
+
| `core/generator/` | Doc generation; PipelineOrchestrator (summarizer, extractor, ner) + LLM; template fallback on failure |
|
|
465
|
+
| `core/exporter/` | Multi-format export for AI coding agents |
|
|
466
|
+
| `core/git/` | Git integration, diff analysis, PreCommitHook (CLI not yet exposed) |
|
|
467
|
+
| `models/` | ML model lifecycle management |
|
|
468
|
+
| `storage/` | ConventionStore, ScoreStore (sql.js), ViolationStore, CustomRuleStore (rules.json) |
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Conventions
|
|
473
|
+
|
|
474
|
+
CodePlug follows these conventions throughout the codebase:
|
|
475
|
+
|
|
476
|
+
### Naming Conventions
|
|
477
|
+
|
|
478
|
+
- **Utility files** — Use camelCase (e.g., `formatDate.ts`, `parseConfig.ts`)
|
|
479
|
+
- **Class/service files** — Use PascalCase (e.g., `ConfigManager.ts`, `ConventionStore.ts`)
|
|
480
|
+
- **React components** — Use PascalCase file names (e.g., `Button.tsx`, `UserProfile.tsx`)
|
|
481
|
+
- **Hooks** — Use "use" prefix with camelCase (e.g., `useAuth.ts`, `useTheme.ts`)
|
|
482
|
+
|
|
483
|
+
### Testing Conventions
|
|
484
|
+
|
|
485
|
+
- **Separate tests/** directory — Integration and e2e tests live outside `src/`
|
|
486
|
+
- **Test file naming** — Use `.test.ts` or `.spec.ts` suffix
|
|
487
|
+
- **Co-located tests** — Use `__tests__/` directories for unit tests near source files
|
|
488
|
+
|
|
489
|
+
### Project Structure Conventions
|
|
490
|
+
|
|
491
|
+
- **Source root** — All source code resides in `src/`
|
|
492
|
+
- **Entry points** — CLI entry at `src/cli/index.ts`
|
|
493
|
+
- **Core modules** — Domain logic in `src/core/` subdirectories by responsibility
|
|
494
|
+
|
|
233
495
|
---
|
|
234
496
|
|
|
235
497
|
## Development
|
|
@@ -265,27 +527,6 @@ npm run dev
|
|
|
265
527
|
|
|
266
528
|
---
|
|
267
529
|
|
|
268
|
-
## Project Structure
|
|
269
|
-
|
|
270
|
-
```
|
|
271
|
-
src/
|
|
272
|
-
cli/commands/ Command handlers (convention, docs, export, config)
|
|
273
|
-
config/ ConfigManager, Zod schemas, types, provider presets
|
|
274
|
-
core/
|
|
275
|
-
analyzer/ AST analysis engine + 6 visitors + PatternAggregator
|
|
276
|
-
classifier/ Drift classification + confidence gating
|
|
277
|
-
scorer/ Compliance scoring, violation detection, auto-fix, trends
|
|
278
|
-
generator/ Doc generation, ML pipelines, LLM client, staleness tracking
|
|
279
|
-
exporter/ Export engine + 5 formatters (Claude, Cursor, Copilot, JSON, CI)
|
|
280
|
-
git/ Git integration + pre-commit hook management
|
|
281
|
-
models/ ML model manager + tier-aware registry
|
|
282
|
-
storage/ ConventionStore, ScoreStore (sql.js), ViolationStore
|
|
283
|
-
templates/ Export templates (Claude, Cursor, Copilot)
|
|
284
|
-
tests/ Unit tests, integration tests, fixture repos
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
---
|
|
288
|
-
|
|
289
530
|
## License
|
|
290
531
|
|
|
291
|
-
MIT
|
|
532
|
+
MIT
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ConventionAuditOptions, ConventionFixOptions, ConventionInitOptions, ConventionScoreOptions } from "../../config/types.js";
|
|
2
2
|
export declare function handleConventionInit(options: ConventionInitOptions): Promise<void>;
|
|
3
3
|
export declare function handleConventionAudit(options: ConventionAuditOptions): Promise<void>;
|
|
4
4
|
export declare function handleConventionDrift(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convention.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/convention.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"convention.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/convention.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAuFf;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAsDf;AAID,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CA6H3D;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxE"}
|
|
@@ -1,62 +1,205 @@
|
|
|
1
1
|
export async function handleConventionInit(options) {
|
|
2
|
-
const chalk = (await import(
|
|
3
|
-
const ora = (await import(
|
|
4
|
-
const {
|
|
5
|
-
const {
|
|
6
|
-
const {
|
|
2
|
+
const chalk = (await import("chalk")).default;
|
|
3
|
+
const ora = (await import("ora")).default;
|
|
4
|
+
const { ConfigManager } = await import("../../config/ConfigManager.js");
|
|
5
|
+
const { AstAnalyzer } = await import("../../core/analyzer/AstAnalyzer.js");
|
|
6
|
+
const { ConventionDetector } = await import("../../core/analyzer/ConventionDetector.js");
|
|
7
|
+
const { ConventionStore } = await import("../../storage/ConventionStore.js");
|
|
7
8
|
const store = new ConventionStore(process.cwd());
|
|
8
|
-
if (!options.force && await store.exists()) {
|
|
9
|
-
console.log(chalk.yellow(
|
|
9
|
+
if (!options.force && (await store.exists())) {
|
|
10
|
+
console.log(chalk.yellow("Conventions already exist. Use -f/--force to re-detect (e.g. npm run convention:init:force)."));
|
|
10
11
|
return;
|
|
11
12
|
}
|
|
12
|
-
const
|
|
13
|
-
|
|
13
|
+
const config = new ConfigManager(process.cwd());
|
|
14
|
+
await config.load();
|
|
15
|
+
const spinner = ora("Analysing codebase...").start();
|
|
16
|
+
const analyzer = new AstAnalyzer(process.cwd(), {
|
|
17
|
+
analysisConfig: config.getAnalysisConfig(),
|
|
18
|
+
structureConfig: config.getStructureConfig(),
|
|
19
|
+
namingConfig: config.getNamingConfig(),
|
|
20
|
+
conventionConfig: config.getConventionConfig(),
|
|
21
|
+
});
|
|
14
22
|
const analysisResult = await analyzer.analyze();
|
|
15
23
|
spinner.succeed(`Analysed ${analysisResult.fileCount} files in ${analysisResult.durationMs}ms`);
|
|
16
|
-
|
|
24
|
+
if (analysisResult.filePaths && analysisResult.filePaths.length >= 3) {
|
|
25
|
+
const spinner2 = ora("Running semantic coherence (HF)...").start();
|
|
26
|
+
try {
|
|
27
|
+
const { detectSemanticPattern } = await import("../../core/analyzer/SemanticCoherencePhase.js");
|
|
28
|
+
const conventionConfig = config.getConventionConfig();
|
|
29
|
+
const semanticPattern = await detectSemanticPattern(process.cwd(), analysisResult.filePaths, config.getModelTier(), {
|
|
30
|
+
useSentenceSimilarityFallback: conventionConfig.useSentenceSimilarityFallback,
|
|
31
|
+
});
|
|
32
|
+
if (semanticPattern) {
|
|
33
|
+
analysisResult.patterns.push(semanticPattern);
|
|
34
|
+
spinner2.succeed(`Semantic coherence: detected (${semanticPattern.confidence}% confidence)`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
spinner2.warn("Semantic coherence: skipped (low confidence or few exports)");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
42
|
+
spinner2.fail(`Semantic coherence: model load failed (${msg})`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const detector = new ConventionDetector({
|
|
46
|
+
conventionConfig: config.getConventionConfig(),
|
|
47
|
+
structureConfig: config.getStructureConfig(),
|
|
48
|
+
modelTier: config.getModelTier(),
|
|
49
|
+
});
|
|
17
50
|
const candidates = await detector.detect(analysisResult);
|
|
18
|
-
const { confirmConventions } = await import(
|
|
51
|
+
const { confirmConventions } = await import("./conventionPrompts.js");
|
|
19
52
|
const confirmed = await confirmConventions(candidates);
|
|
20
53
|
await store.save(confirmed);
|
|
21
54
|
console.log(chalk.green(`\n✅ Conventions saved to .codeplug/conventions.json`));
|
|
22
55
|
console.log(chalk.dim(` Run 'codeplug convention audit' to check current compliance.`));
|
|
23
56
|
}
|
|
24
57
|
export async function handleConventionAudit(options) {
|
|
25
|
-
const chalk = (await import(
|
|
26
|
-
const
|
|
27
|
-
const {
|
|
28
|
-
const {
|
|
58
|
+
const chalk = (await import("chalk")).default;
|
|
59
|
+
const ora = (await import("ora")).default;
|
|
60
|
+
const { ConfigManager } = await import("../../config/ConfigManager.js");
|
|
61
|
+
const { ConventionStore } = await import("../../storage/ConventionStore.js");
|
|
62
|
+
const { ViolationDetector } = await import("../../core/scorer/ViolationDetector.js");
|
|
63
|
+
const { ComplianceScorer } = await import("../../core/scorer/ComplianceScorer.js");
|
|
29
64
|
const store = new ConventionStore(process.cwd());
|
|
30
|
-
if (!await store.exists()) {
|
|
65
|
+
if (!(await store.exists())) {
|
|
31
66
|
console.log(chalk.yellow('No conventions found. Run "codeplug convention init" first.'));
|
|
32
67
|
return;
|
|
33
68
|
}
|
|
34
69
|
const conventions = await store.load();
|
|
35
|
-
const
|
|
70
|
+
const config = new ConfigManager(process.cwd());
|
|
71
|
+
await config.load();
|
|
72
|
+
const oraSpinner = ora("Auditing conventions...").start();
|
|
73
|
+
const detector = new ViolationDetector(process.cwd(), {
|
|
74
|
+
analysisConfig: config.getAnalysisConfig(),
|
|
75
|
+
structureConfig: config.getStructureConfig(),
|
|
76
|
+
namingConfig: config.getNamingConfig(),
|
|
77
|
+
modelTier: config.getModelTier(),
|
|
78
|
+
conventionConfig: config.getConventionConfig(),
|
|
79
|
+
spinner: {
|
|
80
|
+
text: (msg) => {
|
|
81
|
+
oraSpinner.text = msg;
|
|
82
|
+
},
|
|
83
|
+
succeed: (msg) => oraSpinner.succeed(msg),
|
|
84
|
+
},
|
|
85
|
+
});
|
|
36
86
|
const violations = await detector.detect(conventions, options);
|
|
37
|
-
|
|
38
|
-
const
|
|
87
|
+
oraSpinner.succeed(`Audit complete (${violations.length} violation${violations.length === 1 ? "" : "s"})`);
|
|
88
|
+
const scorer = new ComplianceScorer({
|
|
89
|
+
scoringConfig: config.getScoringConfig(),
|
|
90
|
+
});
|
|
91
|
+
const score = await scorer.scoreAndPersist(violations, process.cwd());
|
|
39
92
|
scorer.printReport(score, violations);
|
|
40
93
|
if (options.ci && score.total < (score.threshold ?? 70)) {
|
|
41
94
|
process.exit(1);
|
|
42
95
|
}
|
|
43
96
|
}
|
|
97
|
+
const CODE_EXTENSIONS = /\.(ts|tsx|js|jsx|mjs|cjs)$/;
|
|
44
98
|
export async function handleConventionDrift() {
|
|
45
|
-
const chalk = (await import(
|
|
46
|
-
const
|
|
47
|
-
const {
|
|
99
|
+
const chalk = (await import("chalk")).default;
|
|
100
|
+
const ora = (await import("ora")).default;
|
|
101
|
+
const { ConfigManager } = await import("../../config/ConfigManager.js");
|
|
102
|
+
const { ConventionStore } = await import("../../storage/ConventionStore.js");
|
|
103
|
+
const { ViolationDetector } = await import("../../core/scorer/ViolationDetector.js");
|
|
104
|
+
const { GitIntegration } = await import("../../core/git/GitIntegration.js");
|
|
48
105
|
const store = new ConventionStore(process.cwd());
|
|
49
|
-
if (!await store.exists()) {
|
|
106
|
+
if (!(await store.exists())) {
|
|
50
107
|
console.log(chalk.yellow('No conventions found. Run "codeplug convention init" first.'));
|
|
51
108
|
return;
|
|
52
109
|
}
|
|
110
|
+
const git = new GitIntegration(process.cwd());
|
|
111
|
+
if (!(await git.isGitRepo())) {
|
|
112
|
+
console.log(chalk.red("Not inside a git repository."));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const config = new ConfigManager(process.cwd());
|
|
116
|
+
await config.load();
|
|
53
117
|
const conventions = await store.load();
|
|
54
|
-
|
|
55
|
-
|
|
118
|
+
let commitDiffs;
|
|
119
|
+
try {
|
|
120
|
+
commitDiffs = await git.getRecentCommitDiffs(5);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
console.log(chalk.red("Failed to read git history."));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (commitDiffs.length === 0) {
|
|
127
|
+
console.log(chalk.dim("No recent commits found."));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const changedPaths = new Set();
|
|
131
|
+
const fileToCommit = new Map();
|
|
132
|
+
for (const cd of commitDiffs) {
|
|
133
|
+
for (const f of cd.files) {
|
|
134
|
+
if (!f.binary && CODE_EXTENSIONS.test(f.file)) {
|
|
135
|
+
changedPaths.add(f.file);
|
|
136
|
+
if (!fileToCommit.has(f.file)) {
|
|
137
|
+
fileToCommit.set(f.file, cd.commit.hash.slice(0, 7));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const filePaths = Array.from(changedPaths);
|
|
143
|
+
if (filePaths.length === 0) {
|
|
144
|
+
console.log(chalk.dim("No code files changed in recent commits."));
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const spinner = ora("Auditing changed files for drift...").start();
|
|
148
|
+
const detector = new ViolationDetector(process.cwd(), {
|
|
149
|
+
analysisConfig: config.getAnalysisConfig(),
|
|
150
|
+
structureConfig: config.getStructureConfig(),
|
|
151
|
+
namingConfig: config.getNamingConfig(),
|
|
152
|
+
modelTier: config.getModelTier(),
|
|
153
|
+
conventionConfig: config.getConventionConfig(),
|
|
154
|
+
spinner: {
|
|
155
|
+
text: (msg) => {
|
|
156
|
+
spinner.text = msg;
|
|
157
|
+
},
|
|
158
|
+
succeed: (msg) => spinner.succeed(msg),
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
const violations = await detector.detect(conventions, { filePaths });
|
|
162
|
+
const conventionById = new Map(conventions.map((c) => [c.id, c]));
|
|
163
|
+
const byCommit = new Map();
|
|
164
|
+
for (const v of violations) {
|
|
165
|
+
const commitHash = fileToCommit.get(v.file);
|
|
166
|
+
if (!commitHash)
|
|
167
|
+
continue;
|
|
168
|
+
if (!byCommit.has(commitHash))
|
|
169
|
+
byCommit.set(commitHash, []);
|
|
170
|
+
const convention = conventionById.get(v.conventionId);
|
|
171
|
+
const commitItems = byCommit.get(commitHash);
|
|
172
|
+
if (commitItems) {
|
|
173
|
+
commitItems.push({
|
|
174
|
+
file: v.file,
|
|
175
|
+
rule: convention?.rule ?? v.conventionId,
|
|
176
|
+
message: v.message,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
spinner.stop();
|
|
181
|
+
console.log("");
|
|
182
|
+
console.log(chalk.bold(`Drift Report — ${commitDiffs.length} recent commits scanned`));
|
|
183
|
+
console.log(chalk.dim("─".repeat(50)));
|
|
184
|
+
if (violations.length === 0) {
|
|
185
|
+
console.log(chalk.green("No drift detected. All changes follow conventions."));
|
|
186
|
+
console.log("");
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const drifting = violations.length;
|
|
190
|
+
console.log(chalk.red.bold(`\n Drifting (${drifting}):`));
|
|
191
|
+
for (const [hash, items] of byCommit) {
|
|
192
|
+
for (const { file, rule, message } of items) {
|
|
193
|
+
console.log(chalk.red(` [${hash}] ${file}`));
|
|
194
|
+
console.log(chalk.dim(` Rule: ${rule}`));
|
|
195
|
+
console.log(chalk.dim(` ${message}`));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
console.log("");
|
|
56
199
|
}
|
|
57
200
|
export async function handleConventionScore(options) {
|
|
58
|
-
const chalk = (await import(
|
|
59
|
-
const { ScoreStore } = await import(
|
|
201
|
+
const chalk = (await import("chalk")).default;
|
|
202
|
+
const { ScoreStore } = await import("../../storage/ScoreStore.js");
|
|
60
203
|
const scoreStore = new ScoreStore(process.cwd());
|
|
61
204
|
if (options.trend) {
|
|
62
205
|
await scoreStore.printTrend();
|
|
@@ -71,8 +214,8 @@ export async function handleConventionScore(options) {
|
|
|
71
214
|
}
|
|
72
215
|
}
|
|
73
216
|
export async function handleConventionFix(options) {
|
|
74
|
-
const chalk = (await import(
|
|
75
|
-
const { AutoFixer } = await import(
|
|
217
|
+
const chalk = (await import("chalk")).default;
|
|
218
|
+
const { AutoFixer } = await import("../../core/scorer/AutoFixer.js");
|
|
76
219
|
const fixer = new AutoFixer(process.cwd());
|
|
77
220
|
if (options.id) {
|
|
78
221
|
await fixer.fixById(options.id);
|
|
@@ -85,8 +228,8 @@ export async function handleConventionFix(options) {
|
|
|
85
228
|
}
|
|
86
229
|
}
|
|
87
230
|
export async function handleConventionShow(commit) {
|
|
88
|
-
const chalk = (await import(
|
|
231
|
+
const chalk = (await import("chalk")).default;
|
|
89
232
|
console.log(chalk.dim(`Showing findings for commit ${commit}...`));
|
|
90
|
-
console.log(chalk.yellow(
|
|
233
|
+
console.log(chalk.yellow("Not yet implemented. Coming in Phase 2."));
|
|
91
234
|
}
|
|
92
235
|
//# sourceMappingURL=convention.js.map
|