@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.
Files changed (151) hide show
  1. package/README.md +286 -45
  2. package/dist/cli/commands/convention.d.ts +1 -1
  3. package/dist/cli/commands/convention.d.ts.map +1 -1
  4. package/dist/cli/commands/convention.js +174 -31
  5. package/dist/cli/commands/convention.js.map +1 -1
  6. package/dist/cli/commands/docs.d.ts +3 -1
  7. package/dist/cli/commands/docs.d.ts.map +1 -1
  8. package/dist/cli/commands/docs.js +13 -2
  9. package/dist/cli/commands/docs.js.map +1 -1
  10. package/dist/cli/commands/export.d.ts.map +1 -1
  11. package/dist/cli/commands/export.js +6 -1
  12. package/dist/cli/commands/export.js.map +1 -1
  13. package/dist/cli/commands/start.d.ts +2 -0
  14. package/dist/cli/commands/start.d.ts.map +1 -0
  15. package/dist/cli/commands/start.js +172 -0
  16. package/dist/cli/commands/start.js.map +1 -0
  17. package/dist/cli/index.js +10 -2
  18. package/dist/cli/index.js.map +1 -1
  19. package/dist/config/ConfigManager.d.ts +18 -0
  20. package/dist/config/ConfigManager.d.ts.map +1 -1
  21. package/dist/config/ConfigManager.js +55 -2
  22. package/dist/config/ConfigManager.js.map +1 -1
  23. package/dist/config/ConventionSchema.d.ts +59 -0
  24. package/dist/config/ConventionSchema.d.ts.map +1 -1
  25. package/dist/config/ConventionSchema.js +11 -0
  26. package/dist/config/ConventionSchema.js.map +1 -1
  27. package/dist/config/defaults.d.ts +60 -2
  28. package/dist/config/defaults.d.ts.map +1 -1
  29. package/dist/config/defaults.js +136 -20
  30. package/dist/config/defaults.js.map +1 -1
  31. package/dist/config/types.d.ts +71 -0
  32. package/dist/config/types.d.ts.map +1 -1
  33. package/dist/core/analyzer/AstAnalyzer.d.ts +11 -2
  34. package/dist/core/analyzer/AstAnalyzer.d.ts.map +1 -1
  35. package/dist/core/analyzer/AstAnalyzer.js +21 -5
  36. package/dist/core/analyzer/AstAnalyzer.js.map +1 -1
  37. package/dist/core/analyzer/ConventionDetector.d.ts +12 -1
  38. package/dist/core/analyzer/ConventionDetector.d.ts.map +1 -1
  39. package/dist/core/analyzer/ConventionDetector.js +120 -20
  40. package/dist/core/analyzer/ConventionDetector.js.map +1 -1
  41. package/dist/core/analyzer/ConventionMlResolver.d.ts +4 -0
  42. package/dist/core/analyzer/ConventionMlResolver.d.ts.map +1 -0
  43. package/dist/core/analyzer/ConventionMlResolver.js +17 -0
  44. package/dist/core/analyzer/ConventionMlResolver.js.map +1 -0
  45. package/dist/core/analyzer/PatternAggregator.d.ts +11 -2
  46. package/dist/core/analyzer/PatternAggregator.d.ts.map +1 -1
  47. package/dist/core/analyzer/PatternAggregator.js +87 -15
  48. package/dist/core/analyzer/PatternAggregator.js.map +1 -1
  49. package/dist/core/analyzer/SemanticCoherencePhase.d.ts +10 -0
  50. package/dist/core/analyzer/SemanticCoherencePhase.d.ts.map +1 -0
  51. package/dist/core/analyzer/SemanticCoherencePhase.js +191 -0
  52. package/dist/core/analyzer/SemanticCoherencePhase.js.map +1 -0
  53. package/dist/core/analyzer/SemanticCoherenceService.d.ts +11 -0
  54. package/dist/core/analyzer/SemanticCoherenceService.d.ts.map +1 -0
  55. package/dist/core/analyzer/SemanticCoherenceService.js +56 -0
  56. package/dist/core/analyzer/SemanticCoherenceService.js.map +1 -0
  57. package/dist/core/analyzer/visitors/ComponentVisitor.d.ts.map +1 -1
  58. package/dist/core/analyzer/visitors/ComponentVisitor.js +2 -2
  59. package/dist/core/analyzer/visitors/ComponentVisitor.js.map +1 -1
  60. package/dist/core/analyzer/visitors/ErrorHandlingVisitor.d.ts.map +1 -1
  61. package/dist/core/analyzer/visitors/ErrorHandlingVisitor.js +2 -2
  62. package/dist/core/analyzer/visitors/ErrorHandlingVisitor.js.map +1 -1
  63. package/dist/core/analyzer/visitors/ImportVisitor.d.ts +5 -0
  64. package/dist/core/analyzer/visitors/ImportVisitor.d.ts.map +1 -1
  65. package/dist/core/analyzer/visitors/ImportVisitor.js +8 -3
  66. package/dist/core/analyzer/visitors/ImportVisitor.js.map +1 -1
  67. package/dist/core/analyzer/visitors/NamingVisitor.d.ts +20 -2
  68. package/dist/core/analyzer/visitors/NamingVisitor.d.ts.map +1 -1
  69. package/dist/core/analyzer/visitors/NamingVisitor.js +464 -25
  70. package/dist/core/analyzer/visitors/NamingVisitor.js.map +1 -1
  71. package/dist/core/analyzer/visitors/SchemaVisitor.d.ts +7 -0
  72. package/dist/core/analyzer/visitors/SchemaVisitor.d.ts.map +1 -0
  73. package/dist/core/analyzer/visitors/SchemaVisitor.js +50 -0
  74. package/dist/core/analyzer/visitors/SchemaVisitor.js.map +1 -0
  75. package/dist/core/analyzer/visitors/StructureVisitor.d.ts +4 -1
  76. package/dist/core/analyzer/visitors/StructureVisitor.d.ts.map +1 -1
  77. package/dist/core/analyzer/visitors/StructureVisitor.js +38 -4
  78. package/dist/core/analyzer/visitors/StructureVisitor.js.map +1 -1
  79. package/dist/core/analyzer/visitors/types.d.ts +4 -0
  80. package/dist/core/analyzer/visitors/types.d.ts.map +1 -1
  81. package/dist/core/classifier/CodeBertEmbedder.d.ts +9 -0
  82. package/dist/core/classifier/CodeBertEmbedder.d.ts.map +1 -0
  83. package/dist/core/classifier/CodeBertEmbedder.js +33 -0
  84. package/dist/core/classifier/CodeBertEmbedder.js.map +1 -0
  85. package/dist/core/classifier/ConfidenceGate.d.ts +2 -0
  86. package/dist/core/classifier/ConfidenceGate.d.ts.map +1 -1
  87. package/dist/core/classifier/ConfidenceGate.js +6 -2
  88. package/dist/core/classifier/ConfidenceGate.js.map +1 -1
  89. package/dist/core/exporter/FreshnessChecker.d.ts +5 -1
  90. package/dist/core/exporter/FreshnessChecker.d.ts.map +1 -1
  91. package/dist/core/exporter/FreshnessChecker.js +5 -10
  92. package/dist/core/exporter/FreshnessChecker.js.map +1 -1
  93. package/dist/core/generator/DocGenerator.d.ts +6 -1
  94. package/dist/core/generator/DocGenerator.d.ts.map +1 -1
  95. package/dist/core/generator/DocGenerator.js +62 -7
  96. package/dist/core/generator/DocGenerator.js.map +1 -1
  97. package/dist/core/generator/StalenessTracker.d.ts +7 -1
  98. package/dist/core/generator/StalenessTracker.d.ts.map +1 -1
  99. package/dist/core/generator/StalenessTracker.js +12 -12
  100. package/dist/core/generator/StalenessTracker.js.map +1 -1
  101. package/dist/core/generator/documents/ArchitectureGenerator.d.ts +1 -0
  102. package/dist/core/generator/documents/ArchitectureGenerator.d.ts.map +1 -1
  103. package/dist/core/generator/documents/ArchitectureGenerator.js +37 -12
  104. package/dist/core/generator/documents/ArchitectureGenerator.js.map +1 -1
  105. package/dist/core/generator/documents/ContributingGenerator.d.ts.map +1 -1
  106. package/dist/core/generator/documents/ContributingGenerator.js +20 -13
  107. package/dist/core/generator/documents/ContributingGenerator.js.map +1 -1
  108. package/dist/core/generator/documents/ConventionsGenerator.d.ts.map +1 -1
  109. package/dist/core/generator/documents/ConventionsGenerator.js +16 -2
  110. package/dist/core/generator/documents/ConventionsGenerator.js.map +1 -1
  111. package/dist/core/generator/documents/OnboardingGenerator.d.ts.map +1 -1
  112. package/dist/core/generator/documents/OnboardingGenerator.js +26 -18
  113. package/dist/core/generator/documents/OnboardingGenerator.js.map +1 -1
  114. package/dist/core/generator/documents/ReadmeGenerator.d.ts.map +1 -1
  115. package/dist/core/generator/documents/ReadmeGenerator.js +26 -14
  116. package/dist/core/generator/documents/ReadmeGenerator.js.map +1 -1
  117. package/dist/core/generator/documents/types.d.ts +8 -1
  118. package/dist/core/generator/documents/types.d.ts.map +1 -1
  119. package/dist/core/generator/mlPipelineBuilder.d.ts +8 -0
  120. package/dist/core/generator/mlPipelineBuilder.d.ts.map +1 -0
  121. package/dist/core/generator/mlPipelineBuilder.js +117 -0
  122. package/dist/core/generator/mlPipelineBuilder.js.map +1 -0
  123. package/dist/core/scorer/ComplianceScorer.d.ts +5 -1
  124. package/dist/core/scorer/ComplianceScorer.d.ts.map +1 -1
  125. package/dist/core/scorer/ComplianceScorer.js +47 -23
  126. package/dist/core/scorer/ComplianceScorer.js.map +1 -1
  127. package/dist/core/scorer/ViolationDetector.d.ts +19 -2
  128. package/dist/core/scorer/ViolationDetector.d.ts.map +1 -1
  129. package/dist/core/scorer/ViolationDetector.js +169 -53
  130. package/dist/core/scorer/ViolationDetector.js.map +1 -1
  131. package/dist/models/ModelManager.d.ts +5 -1
  132. package/dist/models/ModelManager.d.ts.map +1 -1
  133. package/dist/models/ModelManager.js +19 -5
  134. package/dist/models/ModelManager.js.map +1 -1
  135. package/dist/models/ModelRegistry.d.ts +1 -1
  136. package/dist/models/ModelRegistry.d.ts.map +1 -1
  137. package/dist/models/ModelRegistry.js +28 -0
  138. package/dist/models/ModelRegistry.js.map +1 -1
  139. package/dist/storage/CustomRuleStore.d.ts +9 -0
  140. package/dist/storage/CustomRuleStore.d.ts.map +1 -0
  141. package/dist/storage/CustomRuleStore.js +22 -0
  142. package/dist/storage/CustomRuleStore.js.map +1 -0
  143. package/dist/storage/ScoreStore.d.ts +2 -5
  144. package/dist/storage/ScoreStore.d.ts.map +1 -1
  145. package/dist/storage/ScoreStore.js +23 -71
  146. package/dist/storage/ScoreStore.js.map +1 -1
  147. package/package.json +4 -3
  148. package/dist/core/classifier/DriftClassifier.d.ts +0 -17
  149. package/dist/core/classifier/DriftClassifier.d.ts.map +0 -1
  150. package/dist/core/classifier/DriftClassifier.js +0 -293
  151. 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
- - **Convention Detection** -- 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.
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
- ## Quick Start
25
+ ### Drift & Compliance
19
26
 
20
- ```bash
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
- # Navigate to your project
25
- cd your-project
29
+ ### Living Documentation
26
30
 
27
- # Detect and confirm conventions
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
- # Check compliance
31
- codeplug convention audit
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, for LLM-enhanced documentation -- any OpenAI-compatible provider works)
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 install
66
+ ### Global Install
47
67
 
48
68
  ```bash
49
69
  npm install -g @dinyangetoh/codeplug-cli
50
70
  ```
51
71
 
52
- ### Local development
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.1GB | ~420MB |
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 { ConventionInitOptions, ConventionAuditOptions, ConventionScoreOptions, ConventionFixOptions } from '../../config/types.js';
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,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAEzI,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BxF;AAED,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB1F;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAc3D;AAED,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAe1F;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAYtF;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxE"}
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('chalk')).default;
3
- const ora = (await import('ora')).default;
4
- const { AstAnalyzer } = await import('../../core/analyzer/AstAnalyzer.js');
5
- const { ConventionDetector } = await import('../../core/analyzer/ConventionDetector.js');
6
- const { ConventionStore } = await import('../../storage/ConventionStore.js');
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('Conventions already exist. Use --force to re-detect.'));
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 spinner = ora('Analysing codebase...').start();
13
- const analyzer = new AstAnalyzer(process.cwd());
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
- const detector = new ConventionDetector();
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('./conventionPrompts.js');
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('chalk')).default;
26
- const { ConventionStore } = await import('../../storage/ConventionStore.js');
27
- const { ViolationDetector } = await import('../../core/scorer/ViolationDetector.js');
28
- const { ComplianceScorer } = await import('../../core/scorer/ComplianceScorer.js');
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 detector = new ViolationDetector(process.cwd());
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
- const scorer = new ComplianceScorer();
38
- const score = scorer.calculate(violations);
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('chalk')).default;
46
- const { ConventionStore } = await import('../../storage/ConventionStore.js');
47
- const { DriftClassifier } = await import('../../core/classifier/DriftClassifier.js');
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
- const classifier = new DriftClassifier();
55
- await classifier.checkRecentCommits(conventions);
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('chalk')).default;
59
- const { ScoreStore } = await import('../../storage/ScoreStore.js');
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('chalk')).default;
75
- const { AutoFixer } = await import('../../core/scorer/AutoFixer.js');
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('chalk')).default;
231
+ const chalk = (await import("chalk")).default;
89
232
  console.log(chalk.dim(`Showing findings for commit ${commit}...`));
90
- console.log(chalk.yellow('Not yet implemented. Coming in Phase 2.'));
233
+ console.log(chalk.yellow("Not yet implemented. Coming in Phase 2."));
91
234
  }
92
235
  //# sourceMappingURL=convention.js.map