@chappibunny/repolens 0.9.0 → 1.1.0

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/CHANGELOG.md CHANGED
@@ -2,6 +2,82 @@
2
2
 
3
3
  All notable changes to RepoLens will be documented in this file.
4
4
 
5
+ ## 1.1.0
6
+
7
+ ### ✨ GitHub Wiki Publisher UX Enhancement
8
+
9
+ Major upgrade to the wiki output quality — better information hierarchy, audience-aware navigation, and richer page structure.
10
+
11
+ - **Audience-grouped Home page**: Pages organized by reader (Stakeholders, Engineers, New Contributors, Change Tracking) instead of a flat list
12
+ - **Page descriptions**: Each link on Home includes a one-line summary of the page's purpose
13
+ - **Status rail**: Home page now shows a metadata table (project, branch, page count, publisher, source)
14
+ - **Recommended reading order**: Guided path through the docs for first-time readers
15
+ - **Grouped sidebar**: Navigation split into Overview and Architecture sections (plus Custom Pages)
16
+ - **Page metadata headers**: Every page gets a `[← Home](Home)` back-link, audience tag, and branch indicator
17
+ - **Cleaner footer**: Compact format with branch context and Home link
18
+ - **New constants**: `PAGE_DESCRIPTIONS`, `AUDIENCE_GROUPS`, `SIDEBAR_GROUPS`, `PAGE_AUDIENCE`
19
+ - **New helpers**: `getPageDisplayTitle()`, `getCustomPageKeys()`, `wikiLink()`, `pageHeader()`
20
+
21
+ ### 🐛 Bug Fixes
22
+ - **Temperature still sent to GPT-5**: `DEFAULT_TEMPERATURE = 0.2` always leaked into API requests even after v1.0.1 fixes — the fallback chain (`temperature ?? aiConfig.temperature ?? DEFAULT_TEMPERATURE`) guaranteed it was never `undefined`. Removed the default entirely; temperature is now only sent when explicitly configured via `REPOLENS_AI_TEMPERATURE` env var or `ai.temperature` in config.
23
+
24
+ ## 1.0.1
25
+
26
+ ### 🐛 Bug Fixes
27
+ - **GPT-5 API compatibility**: Use `max_completion_tokens` instead of deprecated `max_tokens` parameter
28
+ - **GPT-5 temperature handling**: Omit `temperature` from API requests for models that only support the default value (e.g. gpt-5-mini)
29
+ - Removed all hardcoded `temperature: 0.2` overrides from AI section generators
30
+ - Removed `REPOLENS_AI_TEMPERATURE` from CI workflow and `.env.example`
31
+ - Updated `init` scaffolding to omit temperature from default config
32
+
33
+ ### 🔧 Improvements
34
+ - Upgraded GitHub Actions: checkout v4.2.2, setup-node v4.2.0, Node.js 22
35
+
36
+ ## 1.0.0
37
+
38
+ ### 🎉 Stable Release
39
+
40
+ RepoLens v1.0.0 marks the first stable release with a frozen public API. All CLI commands, configuration schema, and plugin interfaces are now covered by semantic versioning guarantees. See [STABILITY.md](STABILITY.md) for the full contract.
41
+
42
+ ### ✨ New Features
43
+ - **GitHub Wiki Publisher**: Publish documentation directly to your repository's Wiki tab
44
+ - Git-based: clones wiki repo, writes pages, commits and pushes
45
+ - Generates `Home.md` index, `_Sidebar.md` navigation, `_Footer.md`
46
+ - Branch filtering via `github_wiki.branches` in `.repolens.yml`
47
+ - Auto-detects repository from `GITHUB_REPOSITORY` env or git remote
48
+ - Token sanitization in error messages (never leaks `GITHUB_TOKEN`)
49
+ - Config: `sidebar` and `footer` toggles
50
+ - 17 tests covering publishing, branch filtering, config validation, and security
51
+
52
+ ### 🐛 Bug Fixes
53
+ - **GPT-5 API compatibility**: Use `max_completion_tokens` instead of deprecated `max_tokens` parameter
54
+ - **GPT-5 temperature handling**: Omit `temperature` from API requests for models that only support the default value (e.g. gpt-5-mini)
55
+ - **Git identity in wiki publisher**: Set committer name/email (`RepoLens Bot`) so CI runners can commit
56
+ - **Publisher allowlist**: Added `github_wiki` to `validate.js` publisher validation (was only in `config-schema.js`)
57
+ - **Doctor false-success**: `repolens doctor` now correctly exits with code 2 when `runDoctor()` reports failures (previously always printed "validation passed")
58
+ - **Feedback exit code**: `repolens feedback` now exits with code 1 when feedback fails to send (previously exited 0)
59
+ - **Unknown flags**: `repolens --unknown-flag` now prints an error instead of silently running publish
60
+ - **scan.ignore security bypass**: Security validator now checks `scan.ignore` patterns (was incorrectly checking non-existent `scan.exclude`)
61
+ - **Domains type mismatch**: Both validators now expect `domains` as an object (was array in security validator, object in schema validator)
62
+ - **Plugin publisher crash isolation**: Plugin publisher errors are now caught and logged instead of crashing the pipeline
63
+
64
+ ### ✅ Config Stability
65
+ - `configVersion: 1` is now **required** (was optional in schema validator)
66
+ - Added `confluence` config section validation (branches array)
67
+ - Added `ai.temperature` range validation (0–2)
68
+ - Added `ai.max_tokens` range validation (>0)
69
+ - AI config values from `.repolens.yml` are now used as fallbacks when env vars are not set
70
+
71
+ ### 🔧 Improvements
72
+ - Standardized exit codes: `EXIT_SUCCESS=0`, `EXIT_ERROR=1`, `EXIT_VALIDATION=2` as named constants
73
+ - Replaced all `console.log`/`console.warn` in production code with logger utilities
74
+ - Removed stale "v0.4.0" references from CLI help text and migrate command
75
+ - Sentry DSN moved to `REPOLENS_SENTRY_DSN` env var (with backwards-compatible default)
76
+ - Hardcoded email in `init` scaffolding replaced with `your-email@example.com` placeholder
77
+
78
+ ### 📄 Documentation
79
+ - Added [STABILITY.md](STABILITY.md): Complete public API contract (CLI, config schema, plugin interface, exit codes, env vars)
80
+
5
81
  ## 0.9.0
6
82
 
7
83
  ### ✨ New Features
package/README.md CHANGED
@@ -16,11 +16,11 @@
16
16
 
17
17
  AI-assisted documentation intelligence system that generates architecture docs for engineers AND readable system docs for stakeholders
18
18
 
19
- **Current Status**: v0.9.0 — Plugin System
19
+ **Current Status**: v1.0.0 — Stable Release
20
20
 
21
21
  RepoLens automatically generates and maintains living architecture documentation by analyzing your repository structure, extracting meaningful insights from your package.json, and creating visual dependency graphs. Run it once, or let it auto-update on every push.
22
22
 
23
- ⚠️ **Early Access Notice**: The CLI commands and configuration format may evolve until v1.0. We will provide migration guides for any breaking changes. v1.0 will guarantee stable CLI behavior and config schema.
23
+ The CLI, configuration schema, and plugin interface are **stable** as of v1.0. See [STABILITY.md](STABILITY.md) for the full API contract and semver guarantees.
24
24
 
25
25
  ---
26
26
 
@@ -49,7 +49,7 @@ For Confluence:
49
49
  ```bash
50
50
  # Edit .env and add:
51
51
  CONFLUENCE_URL=https://your-company.atlassian.net/wiki
52
- CONFLUENCE_EMAIL=trades@rabitaitrades.com
52
+ CONFLUENCE_EMAIL=your-email@example.com
53
53
  CONFLUENCE_API_TOKEN=your-token
54
54
  CONFLUENCE_SPACE_KEY=DOCS
55
55
  ```
@@ -124,7 +124,7 @@ RepoLens automatically detects:
124
124
  ✅ **Deterministic Fallback** - Always generates docs even if AI unavailable
125
125
  ✅ **Business Domain Inference** - Automatically maps code to business functions
126
126
  ✅ **Data Flow Analysis** - Understands how information moves through your system
127
- ✅ **Multiple Publishers** - Output to Notion, Confluence, Markdown, or all three
127
+ ✅ **Multiple Publishers** - Output to Notion, Confluence, GitHub Wiki, Markdown, or all four
128
128
  ✅ **Branch-Aware** - Prevent doc conflicts across branches
129
129
  ✅ **GitHub Actions** - Autonomous operation on every push
130
130
  ✅ **Team Notifications** - Discord integration with rich embeds (NEW in v0.6.0)
@@ -137,6 +137,8 @@ RepoLens automatically detects:
137
137
  ✅ **TypeScript Type Graph** - Map interfaces, classes, and type relationships (NEW in v0.8.0)
138
138
  ✅ **Dependency Graph** - Import analysis with circular dependency detection (NEW in v0.8.0)
139
139
  ✅ **Architecture Drift** - Track structural changes against a baseline (NEW in v0.8.0)
140
+ ✅ **Plugin System** - Extend with custom renderers, publishers, and hooks (NEW in v0.9.0)
141
+ ✅ **Stable API** - CLI, config, and plugin interface frozen with semver guarantees (v1.0.0)
140
142
 
141
143
  ---
142
144
 
@@ -228,7 +230,7 @@ npm link
228
230
  Install from a specific version:
229
231
 
230
232
  ```bash
231
- npm install https://github.com/CHAPIBUNNY/repolens/releases/download/v0.9.0/chappibunny-repolens-0.9.0.tgz
233
+ npm install https://github.com/CHAPIBUNNY/repolens/releases/download/v1.0.0/chappibunny-repolens-1.0.0.tgz
232
234
  ```
233
235
  </details>
234
236
 
@@ -311,6 +313,14 @@ publishers:
311
313
  ```
312
314
  Maximum visibility: Notion for async collaboration, Confluence for enterprise docs, Markdown for local backups.
313
315
 
316
+ **GitHub Wiki** (ideal for open source):
317
+ ```yaml
318
+ publishers:
319
+ - github_wiki
320
+ - markdown
321
+ ```
322
+ Docs live alongside your code — accessible from the repo's Wiki tab. Requires `GITHUB_TOKEN`.
323
+
314
324
  ### Step 3: Enable AI Features (Optional)
315
325
 
316
326
  **AI-enhanced documentation adds natural language explanations for non-technical audiences.**
@@ -318,7 +328,7 @@ Maximum visibility: Notion for async collaboration, Confluence for enterprise do
318
328
  **3.1: Choose an AI Provider**
319
329
 
320
330
  RepoLens works with any OpenAI-compatible API:
321
- - **OpenAI** (gpt-4-turbo-preview, gpt-3.5-turbo)
331
+ - **OpenAI** (gpt-5-mini, gpt-5.4, gpt-5-nano)
322
332
  - **Anthropic Claude** (via API gateway)
323
333
  - **Azure OpenAI** (enterprise deployments)
324
334
  - **Local Models** (Ollama, LM Studio, etc.)
@@ -333,8 +343,7 @@ REPOLENS_AI_API_KEY=sk-xxxxxxxxxxxxx
333
343
 
334
344
  # Optional: Customize provider
335
345
  REPOLENS_AI_BASE_URL=https://api.openai.com/v1
336
- REPOLENS_AI_MODEL=gpt-4-turbo-preview
337
- REPOLENS_AI_TEMPERATURE=0.3
346
+ REPOLENS_AI_MODEL=gpt-5-mini
338
347
  REPOLENS_AI_MAX_TOKENS=2000
339
348
  ```
340
349
 
@@ -344,7 +353,6 @@ REPOLENS_AI_MAX_TOKENS=2000
344
353
  ai:
345
354
  enabled: true # Enable AI features
346
355
  mode: hybrid # hybrid, full, or off
347
- temperature: 0.3 # Lower = more focused (0.0-1.0)
348
356
  max_tokens: 2000 # Token limit per request
349
357
 
350
358
  features:
@@ -356,7 +364,7 @@ features:
356
364
  change_impact: true # Architecture diff with context
357
365
  ```
358
366
 
359
- **Cost Estimates** (with gpt-4-turbo-preview):
367
+ **Cost Estimates** (with gpt-5-mini):
360
368
  - Small repo (<50 files): $0.10-$0.30 per run
361
369
  - Medium repo (50-200 files): $0.30-$0.80 per run
362
370
  - Large repo (200+ files): $0.80-$2.00 per run
@@ -428,7 +436,7 @@ If using the Confluence publisher:
428
436
  Create `.env` in your project root:
429
437
  ```bash
430
438
  CONFLUENCE_URL=https://your-company.atlassian.net/wiki
431
- CONFLUENCE_EMAIL=trades@rabitaitrades.com
439
+ CONFLUENCE_EMAIL=your-email@example.com
432
440
  CONFLUENCE_API_TOKEN=your-api-token-here
433
441
  CONFLUENCE_SPACE_KEY=DOCS
434
442
  CONFLUENCE_PARENT_PAGE_ID=123456789 # Optional
@@ -449,7 +457,7 @@ Add as repository secrets:
449
457
  2. Click **"New repository secret"**
450
458
  3. Add:
451
459
  - Name: `CONFLUENCE_URL`, Value: `https://your-company.atlassian.net/wiki`
452
- - Name: `CONFLUENCE_EMAIL`, Value: `trades@rabitaitrades.com`
460
+ - Name: `CONFLUENCE_EMAIL`, Value: `your-email@example.com`
453
461
  - Name: `CONFLUENCE_API_TOKEN`, Value: `your-token`
454
462
  - Name: `CONFLUENCE_SPACE_KEY`, Value: `DOCS`
455
463
  - Name: `CONFLUENCE_PARENT_PAGE_ID`, Value: `123456789` (optional)
@@ -939,13 +947,17 @@ features:
939
947
 
940
948
  | Field | Type | Required | Description |
941
949
  |-------|------|----------|-------------|
942
- | `configVersion` | number | No | Schema version (current: 1) for future migrations |
950
+ | `configVersion` | number | **Yes** | Schema version (must be `1`) |
943
951
  | `project.name` | string | Yes | Project name |
944
952
  | `project.docs_title_prefix` | string | No | Prefix for documentation titles (default: project name) |
945
- | `publishers` | array | Yes | Output targets: `notion`, `confluence`, `markdown` |
953
+ | `publishers` | array | Yes | Output targets: `notion`, `confluence`, `github_wiki`, `markdown` (+ plugin publishers) |
954
+ | `plugins` | array | No | Plugin paths or npm package names |
946
955
  | `notion.branches` | array | No | Branch whitelist for Notion publishing. Supports globs. |
947
956
  | `notion.includeBranchInTitle` | boolean | No | Add `[branch-name]` to titles (default: `true`) |
948
957
  | `confluence.branches` | array | No | Branch whitelist for Confluence publishing. Supports globs. |
958
+ | `github_wiki.branches` | array | No | Branch whitelist for GitHub Wiki publishing. Supports globs. |
959
+ | `github_wiki.sidebar` | boolean | No | Generate `_Sidebar.md` navigation (default: `true`) |
960
+ | `github_wiki.footer` | boolean | No | Generate `_Footer.md` (default: `true`) |
949
961
  | `discord.enabled` | boolean | No | Enable Discord notifications (default: `true` if webhook set) |
950
962
  | `discord.notifyOn` | string | No | Notification policy: `always`, `significant`, `never` (default: `significant`) |
951
963
  | `discord.significantThreshold` | number | No | Change % threshold for notifications (default: `10`) |
@@ -956,7 +968,11 @@ features:
956
968
  | `scan.ignore` | array | Yes | Glob patterns to exclude |
957
969
  | `module_roots` | array | No | Root directories for module detection |
958
970
  | `outputs.pages` | array | Yes | Documentation pages to generate |
959
- | `features` | object | No | Experimental feature flags |
971
+ | `features` | object | No | Feature flags (boolean values) |
972
+ | `ai.enabled` | boolean | No | Enable AI-powered documentation |
973
+ | `ai.mode` | string | No | AI mode: `hybrid`, `full`, or `off` |
974
+ | `ai.temperature` | number | No | Generation temperature (0–2). Not supported by all models (e.g. gpt-5-mini ignores it) |
975
+ | `ai.max_tokens` | number | No | Max completion tokens per request (>0) |
960
976
 
961
977
  ---
962
978
 
@@ -986,6 +1002,13 @@ Optional for Discord notifications:
986
1002
  |----------|----------|-------------|
987
1003
  | `DISCORD_WEBHOOK_URL` | No | Discord webhook URL for team notifications |
988
1004
 
1005
+ Required for GitHub Wiki publisher:
1006
+
1007
+ | Variable | Required | Description |
1008
+ |----------|----------|-------------|
1009
+ | `GITHUB_TOKEN` | Yes | Personal access token or Actions `${{ secrets.GITHUB_TOKEN }}` |
1010
+ | `GITHUB_REPOSITORY` | No | `owner/repo` (auto-detected from git remote in Actions) |
1011
+
989
1012
  **Local Development:** Create `.env` file in project root
990
1013
  **GitHub Actions:** Add as repository secrets in Settings → Secrets and variables → Actions
991
1014
 
@@ -1070,7 +1093,7 @@ npm test
1070
1093
  - Integration workflows
1071
1094
  - Doctor command validation
1072
1095
 
1073
- **Coverage:** 163 tests passing across 14 test files
1096
+ **Coverage:** 180 tests passing across 15 test files
1074
1097
 
1075
1098
  ### Test Package Installation Locally
1076
1099
 
@@ -1081,7 +1104,7 @@ Simulates the full user installation experience:
1081
1104
  npm pack
1082
1105
 
1083
1106
  # Install globally from tarball
1084
- npm install -g chappibunny-repolens-0.9.0.tgz
1107
+ npm install -g chappibunny-repolens-1.0.0.tgz
1085
1108
 
1086
1109
  # Verify
1087
1110
  repolens --version
@@ -1130,11 +1153,15 @@ repolens/
1130
1153
  │ │ ├── publish.js # Publishing pipeline
1131
1154
  │ │ ├── notion.js # Notion API integration
1132
1155
  │ │ ├── confluence.js # Confluence REST API integration
1156
+ │ │ ├── github-wiki.js # GitHub Wiki publisher (git-based)
1133
1157
  │ │ └── markdown.js # Local Markdown generation
1134
1158
  │ ├── integrations/
1135
1159
  │ │ └── discord.js # Discord webhook notifications
1136
1160
  │ ├── delivery/
1137
1161
  │ │ └── comment.js # PR comment delivery
1162
+ │ ├── plugins/
1163
+ │ │ ├── loader.js # Plugin resolution and dynamic import
1164
+ │ │ └── manager.js # Plugin registry and lifecycle orchestration
1138
1165
  │ └── utils/
1139
1166
  │ ├── logger.js # Logging utilities
1140
1167
  │ ├── retry.js # API retry logic (exponential backoff)
@@ -1146,10 +1173,11 @@ repolens/
1146
1173
  │ ├── telemetry.js # Opt-in error tracking + performance timers
1147
1174
  │ ├── errors.js # Enhanced error messages with guidance
1148
1175
  │ └── update-check.js # Version update notifications
1149
- ├── tests/ # Vitest test suite (163 tests across 14 files)
1176
+ ├── tests/ # Vitest test suite (180 tests across 15 files)
1150
1177
  ├── .repolens.yml # Dogfooding config
1151
1178
  ├── package.json
1152
1179
  ├── CHANGELOG.md
1180
+ ├── STABILITY.md
1153
1181
  ├── RELEASE.md
1154
1182
  └── ROADMAP.md
1155
1183
  ```
@@ -1163,13 +1191,13 @@ RepoLens uses automated GitHub Actions releases.
1163
1191
  ### Creating a Release
1164
1192
 
1165
1193
  ```bash
1166
- # Patch version (0.9.0 → 0.9.1) - Bug fixes
1194
+ # Patch version (1.0.0 → 1.0.1) - Bug fixes
1167
1195
  npm run release:patch
1168
1196
 
1169
- # Minor version (0.9.0 → 0.10.0) - New features
1197
+ # Minor version (1.0.0 → 1.1.0) - New features
1170
1198
  npm run release:minor
1171
1199
 
1172
- # Major version (0.9.0 → 1.0.0) - Breaking changes
1200
+ # Major version (1.0.0 → 2.0.0) - Breaking changes
1173
1201
  npm run release:major
1174
1202
 
1175
1203
  # Push the tag to trigger workflow
@@ -1189,26 +1217,25 @@ See [RELEASE.md](./RELEASE.md) for detailed workflow.
1189
1217
 
1190
1218
  ## 🤝 Contributing
1191
1219
 
1192
- RepoLens is currently in early access. v1.0 will open for community contributions.
1193
-
1194
1220
  **Ways to help:**
1195
1221
  - **Try it out**: Install and use in your projects
1196
1222
  - **Report issues**: Share bugs, edge cases, or UX friction
1197
1223
  - **Request features**: Tell us what's missing
1198
- - **Share feedback**: What works? What doesn't?
1224
+ - **Build plugins**: Extend RepoLens with custom renderers and publishers
1225
+ - **Share feedback**: `repolens feedback`
1199
1226
 
1200
1227
  ---
1201
1228
 
1202
- ## 🗺️ Roadmap to v1.0
1229
+ ## 🗺️ Roadmap
1203
1230
 
1204
- **Current Status:** v0.9.0 — Plugin System
1231
+ **Current Status:** v1.0.0 — Stable Release
1205
1232
 
1206
- ### Completed
1233
+ ### v1.0 — Complete
1207
1234
 
1208
1235
  - [x] CLI commands: `init`, `doctor`, `publish`, `migrate`, `watch`, `feedback`, `version`, `help`
1209
- - [x] Config schema v1 with validation
1236
+ - [x] Config schema v1 with validation (frozen)
1210
1237
  - [x] Auto-discovery of `.repolens.yml`
1211
- - [x] Publishers: Notion + Confluence + Markdown
1238
+ - [x] Publishers: Notion + Confluence + GitHub Wiki + Markdown
1212
1239
  - [x] Branch-aware publishing with filtering
1213
1240
  - [x] Smart tech stack detection from package.json
1214
1241
  - [x] Unicode dependency diagrams (no external deps)
@@ -1217,7 +1244,7 @@ RepoLens is currently in early access. v1.0 will open for community contribution
1217
1244
  - [x] GitHub Actions automation (publish + release)
1218
1245
  - [x] PR architecture diff comments
1219
1246
  - [x] Performance guardrails (10k warning, 50k limit)
1220
- - [x] Comprehensive test suite (163 tests across 14 files)
1247
+ - [x] Comprehensive test suite (180 tests across 15 files)
1221
1248
  - [x] Security hardening (secret detection, injection prevention, fuzzing)
1222
1249
  - [x] Discord notifications with rich embeds
1223
1250
  - [x] Documentation coverage & health scoring
@@ -1235,11 +1262,14 @@ RepoLens is currently in early access. v1.0 will open for community contribution
1235
1262
  - [x] Dependency graph with circular dependency detection
1236
1263
  - [x] Architecture drift detection (baseline comparison)
1237
1264
  - [x] Plugin system for custom renderers and publishers
1265
+ - [x] Stability audit: CLI, config schema, and plugin interface frozen
1266
+ - [x] [STABILITY.md](STABILITY.md): Public API contract with semver guarantees
1238
1267
 
1239
- ### Planned for v1.0 🎯
1268
+ ### Future
1240
1269
 
1241
- - [ ] Stability audit: freeze CLI flags and config schema
1242
- - [ ] Additional publishers (GitHub Wiki, Obsidian)
1270
+ - [ ] Additional publishers (Obsidian)
1271
+ - [ ] VS Code extension
1272
+ - [ ] GitHub App
1243
1273
 
1244
1274
  See [ROADMAP.md](./ROADMAP.md) for detailed planning.
1245
1275
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chappibunny/repolens",
3
- "version": "0.9.0",
3
+ "version": "1.1.0",
4
4
  "description": "AI-assisted documentation intelligence system for technical and non-technical audiences",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -25,7 +25,6 @@ export async function generateExecutiveSummary(context) {
25
25
  const result = await generateText({
26
26
  system: SYSTEM_PROMPT,
27
27
  user: createExecutiveSummaryPrompt(context),
28
- temperature: 0.2,
29
28
  maxTokens: 1500
30
29
  });
31
30
 
@@ -47,7 +46,6 @@ export async function generateSystemOverview(context) {
47
46
  const result = await generateText({
48
47
  system: SYSTEM_PROMPT,
49
48
  user: createSystemOverviewPrompt(context),
50
- temperature: 0.2,
51
49
  maxTokens: 1200
52
50
  });
53
51
 
@@ -68,7 +66,6 @@ export async function generateBusinessDomains(context) {
68
66
  const result = await generateText({
69
67
  system: SYSTEM_PROMPT,
70
68
  user: createBusinessDomainsPrompt(context),
71
- temperature: 0.2,
72
69
  maxTokens: 2000
73
70
  });
74
71
 
@@ -89,7 +86,6 @@ export async function generateArchitectureOverview(context) {
89
86
  const result = await generateText({
90
87
  system: SYSTEM_PROMPT,
91
88
  user: createArchitectureOverviewPrompt(context),
92
- temperature: 0.2,
93
89
  maxTokens: 1800
94
90
  });
95
91
 
@@ -110,7 +106,6 @@ export async function generateDataFlows(flows, context) {
110
106
  const result = await generateText({
111
107
  system: SYSTEM_PROMPT,
112
108
  user: createDataFlowsPrompt(flows, context),
113
- temperature: 0.2,
114
109
  maxTokens: 1800
115
110
  });
116
111
 
@@ -131,7 +126,6 @@ export async function generateDeveloperOnboarding(context) {
131
126
  const result = await generateText({
132
127
  system: SYSTEM_PROMPT,
133
128
  user: createDeveloperOnboardingPrompt(context),
134
- temperature: 0.2,
135
129
  maxTokens: 2200
136
130
  });
137
131
 
@@ -4,12 +4,12 @@ import { warn, info } from "../utils/logger.js";
4
4
  import { executeAIRequest } from "../utils/rate-limit.js";
5
5
 
6
6
  const DEFAULT_TIMEOUT_MS = 60000;
7
- const DEFAULT_TEMPERATURE = 0.2;
8
7
  const DEFAULT_MAX_TOKENS = 2500;
9
8
 
10
- export async function generateText({ system, user, temperature, maxTokens }) {
11
- // Check if AI is enabled
12
- const enabled = process.env.REPOLENS_AI_ENABLED === "true";
9
+ export async function generateText({ system, user, temperature, maxTokens, config }) {
10
+ // Check if AI is enabled (env var takes precedence, then config)
11
+ const aiConfig = config?.ai || {};
12
+ const enabled = process.env.REPOLENS_AI_ENABLED === "true" || aiConfig.enabled === true;
13
13
 
14
14
  if (!enabled) {
15
15
  return {
@@ -19,13 +19,17 @@ export async function generateText({ system, user, temperature, maxTokens }) {
19
19
  };
20
20
  }
21
21
 
22
- // Get provider configuration from environment
22
+ // Get provider configuration (env vars take precedence, then config, then defaults)
23
23
  const provider = process.env.REPOLENS_AI_PROVIDER || "openai_compatible";
24
24
  const baseUrl = process.env.REPOLENS_AI_BASE_URL;
25
25
  const apiKey = process.env.REPOLENS_AI_API_KEY;
26
- const model = process.env.REPOLENS_AI_MODEL || "gpt-4-turbo-preview";
26
+ const model = process.env.REPOLENS_AI_MODEL || "gpt-5-mini";
27
27
  const timeoutMs = parseInt(process.env.REPOLENS_AI_TIMEOUT_MS || DEFAULT_TIMEOUT_MS);
28
28
 
29
+ // Use config values as fallback for maxTokens; temperature only when explicitly set
30
+ const resolvedTemp = temperature ?? aiConfig.temperature ?? undefined;
31
+ const resolvedMaxTokens = maxTokens ?? aiConfig.max_tokens ?? DEFAULT_MAX_TOKENS;
32
+
29
33
  // Validate configuration
30
34
  if (!apiKey) {
31
35
  warn("REPOLENS_AI_API_KEY not set. AI features disabled.");
@@ -47,8 +51,8 @@ export async function generateText({ system, user, temperature, maxTokens }) {
47
51
  model,
48
52
  system,
49
53
  user,
50
- temperature: temperature ?? DEFAULT_TEMPERATURE,
51
- maxTokens: maxTokens ?? DEFAULT_MAX_TOKENS,
54
+ temperature: resolvedTemp,
55
+ maxTokens: resolvedMaxTokens,
52
56
  timeoutMs
53
57
  });
54
58
 
@@ -76,21 +80,28 @@ async function callOpenAICompatibleAPI({ baseUrl, apiKey, model, system, user, t
76
80
  const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
77
81
 
78
82
  try {
83
+ // Build request body — omit temperature if not supported by model
84
+ const body = {
85
+ model,
86
+ messages: [
87
+ { role: "system", content: system },
88
+ { role: "user", content: user }
89
+ ],
90
+ max_completion_tokens: maxTokens
91
+ };
92
+ // Only send temperature when explicitly configured — some models
93
+ // (e.g. gpt-5-mini) reject any non-default value
94
+ if (temperature != null) {
95
+ body.temperature = temperature;
96
+ }
97
+
79
98
  const response = await fetch(url, {
80
99
  method: "POST",
81
100
  headers: {
82
101
  "Content-Type": "application/json",
83
102
  "Authorization": `Bearer ${apiKey}`
84
103
  },
85
- body: JSON.stringify({
86
- model,
87
- messages: [
88
- { role: "system", content: system },
89
- { role: "user", content: user }
90
- ],
91
- temperature,
92
- max_tokens: maxTokens
93
- }),
104
+ body: JSON.stringify(body),
94
105
  signal: controller.signal
95
106
  });
96
107
 
@@ -129,9 +140,9 @@ export function getAIConfig() {
129
140
  return {
130
141
  enabled: isAIEnabled(),
131
142
  provider: process.env.REPOLENS_AI_PROVIDER || "openai_compatible",
132
- model: process.env.REPOLENS_AI_MODEL || "gpt-4-turbo-preview",
143
+ model: process.env.REPOLENS_AI_MODEL || "gpt-5-mini",
133
144
  hasApiKey: !!process.env.REPOLENS_AI_API_KEY,
134
- temperature: parseFloat(process.env.REPOLENS_AI_TEMPERATURE || DEFAULT_TEMPERATURE),
145
+ temperature: process.env.REPOLENS_AI_TEMPERATURE ? parseFloat(process.env.REPOLENS_AI_TEMPERATURE) : undefined,
135
146
  maxTokens: parseInt(process.env.REPOLENS_AI_MAX_TOKENS || DEFAULT_MAX_TOKENS)
136
147
  };
137
148
  }
package/src/cli.js CHANGED
@@ -41,6 +41,11 @@ import {
41
41
  } from "./utils/telemetry.js";
42
42
  import { createInterface } from "node:readline";
43
43
 
44
+ // Standardized exit codes
45
+ const EXIT_SUCCESS = 0;
46
+ const EXIT_ERROR = 1;
47
+ const EXIT_VALIDATION = 2;
48
+
44
49
  function formatDuration(ms) {
45
50
  if (ms < 1000) return `${ms}ms`;
46
51
  return `${(ms / 1000).toFixed(1)}s`;
@@ -136,7 +141,7 @@ Usage:
136
141
  Commands:
137
142
  init Scaffold RepoLens files in your repository
138
143
  doctor Validate your RepoLens setup
139
- migrate Upgrade workflow files to v0.4.0 format
144
+ migrate Upgrade workflow files to current format
140
145
  publish Scan, render, and publish documentation
141
146
  watch Watch for file changes and regenerate docs
142
147
  feedback Send feedback to the RepoLens team
@@ -213,7 +218,7 @@ async function main() {
213
218
  error("Failed to initialize RepoLens:");
214
219
  error(err.message);
215
220
  await closeTelemetry();
216
- process.exit(1);
221
+ process.exit(EXIT_ERROR);
217
222
  }
218
223
  return;
219
224
  }
@@ -225,10 +230,16 @@ async function main() {
225
230
 
226
231
  const timer = startTimer("doctor");
227
232
  try {
228
- await runDoctor(targetDir);
233
+ const result = await runDoctor(targetDir);
229
234
  const duration = stopTimer(timer);
230
- info("✓ RepoLens validation passed");
231
235
 
236
+ if (result && result.ok === false) {
237
+ trackUsage("doctor", "failure", { duration });
238
+ await closeTelemetry();
239
+ process.exit(EXIT_VALIDATION);
240
+ }
241
+
242
+ info("✓ RepoLens validation passed");
232
243
  trackUsage("doctor", "success", { duration });
233
244
  await closeTelemetry();
234
245
  } catch (err) {
@@ -238,7 +249,7 @@ async function main() {
238
249
  error("Validation failed:");
239
250
  error(err.message);
240
251
  await closeTelemetry();
241
- process.exit(2);
252
+ process.exit(EXIT_VALIDATION);
242
253
  }
243
254
  return;
244
255
  }
@@ -267,7 +278,7 @@ async function main() {
267
278
  error("Migration failed:");
268
279
  error(err.message);
269
280
  await closeTelemetry();
270
- process.exit(1);
281
+ process.exit(EXIT_ERROR);
271
282
  }
272
283
  return;
273
284
  }
@@ -280,13 +291,20 @@ async function main() {
280
291
  info(`Using config: ${configPath}`);
281
292
  } catch (err) {
282
293
  error(err.message);
283
- process.exit(2);
294
+ process.exit(EXIT_VALIDATION);
284
295
  }
285
296
  await runWatch(configPath);
286
297
  return;
287
298
  }
288
299
 
289
- if (command === "publish" || !command || command.startsWith("--")) {
300
+ // Reject unknown flags/commands before falling through to publish
301
+ if (command && command.startsWith("--") && !["--help", "-h", "--version", "-v"].includes(command)) {
302
+ error(`Unknown option: ${command}`);
303
+ error("Run 'repolens help' for usage information.");
304
+ process.exit(EXIT_ERROR);
305
+ }
306
+
307
+ if (command === "publish" || !command) {
290
308
  await printBanner();
291
309
 
292
310
  const commandTimer = startTimer("publish");
@@ -299,7 +317,7 @@ async function main() {
299
317
  } catch (err) {
300
318
  stopTimer(commandTimer);
301
319
  error(err.message);
302
- process.exit(2);
320
+ process.exit(EXIT_VALIDATION);
303
321
  }
304
322
 
305
323
  let cfg, scan;
@@ -312,7 +330,7 @@ async function main() {
312
330
  trackUsage("publish", "failure", { step: "config-load" });
313
331
  error(formatError("CONFIG_VALIDATION_FAILED", err));
314
332
  await closeTelemetry();
315
- process.exit(2);
333
+ process.exit(EXIT_VALIDATION);
316
334
  }
317
335
 
318
336
  // Load plugins
@@ -342,7 +360,7 @@ async function main() {
342
360
  : err.message?.includes("limit") ? "SCAN_TOO_MANY_FILES" : null;
343
361
  error(code ? formatError(code, err) : `Failed to scan repository:\n ${err.message}`);
344
362
  await closeTelemetry();
345
- process.exit(1);
363
+ process.exit(EXIT_ERROR);
346
364
  }
347
365
 
348
366
  const rawDiff = getGitDiff("origin/main");
@@ -399,7 +417,7 @@ async function main() {
399
417
  error("Failed to publish documentation:");
400
418
  error(err.message);
401
419
  await closeTelemetry();
402
- process.exit(1);
420
+ process.exit(EXIT_ERROR);
403
421
  }
404
422
 
405
423
  await closeTelemetry();
@@ -423,7 +441,7 @@ async function main() {
423
441
  if (!message.trim()) {
424
442
  error("Feedback message cannot be empty.");
425
443
  await closeTelemetry();
426
- process.exit(1);
444
+ process.exit(EXIT_ERROR);
427
445
  }
428
446
 
429
447
  info("\nSending feedback...");
@@ -437,6 +455,8 @@ async function main() {
437
455
  info("✓ Thank you! Your feedback has been sent.");
438
456
  } else {
439
457
  error("Failed to send feedback. Please try again later.");
458
+ await closeTelemetry();
459
+ process.exit(EXIT_ERROR);
440
460
  }
441
461
  } catch (err) {
442
462
  rl.close();
@@ -451,7 +471,7 @@ async function main() {
451
471
 
452
472
  error(`Unknown command: ${command}`);
453
473
  error("Available commands: init, doctor, migrate, publish, watch, feedback, version, help");
454
- process.exit(1);
474
+ process.exit(EXIT_ERROR);
455
475
  }
456
476
 
457
477
  main().catch(async (err) => {
@@ -481,5 +501,5 @@ main().catch(async (err) => {
481
501
  }
482
502
 
483
503
  await closeTelemetry();
484
- process.exit(1);
504
+ process.exit(EXIT_ERROR);
485
505
  });