Skip to content

Commit 8b28b95

Browse files
authored
Merge pull request #38 from wai-coding/dev
feat: summary polish, config coverage, and deployment readiness docs
2 parents 9cf7c3a + c488cb2 commit 8b28b95

4 files changed

Lines changed: 127 additions & 22 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## v5 — Summary Polish and Config Coverage
4+
5+
- Improved human summary generator with complete sentence enforcement and deploy-readiness detection
6+
- Expanded config test coverage to verify all rules are wired into defaults, presets, and registry
7+
- Added deployment readiness section to README
8+
- Strengthened export workflow bullet validation with period-ending requirement
9+
310
## v4 — Tooling Improvements
411

512
- Stronger auto-fix engine with detailed skip reporting

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,17 @@ Download the `inspectorepo-report` artifact from the Actions tab to see the full
384384
- [ ] Dependency graph and cascade analysis
385385
- [ ] Performance profiling for large codebases
386386

387+
## Deployment Readiness
388+
389+
The InspectoRepo web UI is currently in **Preview**. It is stable enough for local experimentation and demo purposes but is not yet deployed as a hosted service.
390+
391+
- **Browser support:** The folder picker requires the File System Access API (Chrome or Edge). Other browsers can use the Upload Folder fallback or the "Try with sample project" button.
392+
- **Onboarding:** The app shows a clear About section explaining how to run an analysis, with browser capability detection and a sample project for instant exploration.
393+
- **Empty state:** When no issues are found, the UI displays a friendly confirmation with the analysis score.
394+
- **Preview badge:** A visible "Preview" badge in the top bar signals the product is under active development.
395+
396+
For production deployment, the web app is a standard Vite/React build (`npm run build`) and can be served from any static hosting provider.
397+
387398
## Custom Rule API
388399

389400
Extend InspectoRepo with your own rules using `defineRule()`:

ai/scripts/generate-repomix-exports.ts

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -147,20 +147,20 @@ function categorizeFiles(files: string[]): Map<string, string[]> {
147147
return groups;
148148
}
149149

150-
// Polished, outcome-focused bullet templates per area (≥8 words, verb-first)
150+
// Polished, outcome-focused bullet templates per area (≥8 words, verb-first, complete sentences)
151151
const AREA_BULLET_TEMPLATES: Record<string, string> = {
152-
core: 'Expanded rule coverage with stronger detection accuracy and richer diagnostics',
153-
cli: 'Enhanced the command-line interface for a smoother developer experience',
154-
shared: 'Refined shared type definitions to improve consistency across all packages',
155-
'vscode-extension': 'Improved the VS Code extension for faster in-editor feedback',
156-
web: 'Polished the web interface for a more intuitive analysis workflow',
157-
docs: 'Updated documentation to reflect the latest codebase improvements and conventions',
158-
ai: 'Strengthened the export workflow so summaries are cleaner and more reliable',
159-
workflow: 'Improved the CI pipeline to catch more issues before code ships',
160-
examples: 'Updated example fixtures to demonstrate current rule coverage and patterns',
161-
screenshots: 'Refreshed screenshots and demo automation for accurate visual documentation',
162-
root: 'Updated root project configuration for better workspace consistency',
163-
other: 'Improved project tooling and overall developer workflow configuration quality',
152+
core: 'Expanded rule coverage with stronger detection accuracy and richer diagnostics.',
153+
cli: 'Enhanced the command-line interface for a smoother developer experience.',
154+
shared: 'Refined shared type definitions to improve consistency across all packages.',
155+
'vscode-extension': 'Improved the VS Code extension for faster in-editor feedback.',
156+
web: 'Polished the web interface for a more intuitive analysis workflow.',
157+
docs: 'Updated documentation to reflect the latest codebase improvements and conventions.',
158+
ai: 'Strengthened the export workflow so summaries are cleaner and more reliable.',
159+
workflow: 'Improved the CI pipeline to catch more issues before code ships.',
160+
examples: 'Updated example fixtures to demonstrate current rule coverage and patterns.',
161+
screenshots: 'Refreshed screenshots and demo automation for accurate visual documentation.',
162+
root: 'Updated root project configuration for better workspace consistency.',
163+
other: 'Improved project tooling and overall developer workflow configuration quality.',
164164
};
165165

166166
// Banned patterns — bullets containing any of these are considered noisy/internal
@@ -290,6 +290,8 @@ function isQualityBullet(bullet: string): boolean {
290290
if (!/^[A-Z][a-z]/.test(trimmed)) return false;
291291
// Must be at least 8 words
292292
if (trimmed.split(/\s+/).length < 8) return false;
293+
// Must end with a period (complete sentence)
294+
if (!trimmed.endsWith('.')) return false;
293295
// Must not contain file names (e.g. foo.ts, bar.tsx, baz.md)
294296
if (/\b\w+\.\w{1,4}\b/.test(trimmed) && /\.(ts|tsx|js|jsx|md|json|yml|yaml|css|html)/.test(trimmed)) return false;
295297
// Must not contain colon-prefixed commit text (e.g. "feat: ...")
@@ -299,6 +301,19 @@ function isQualityBullet(bullet: string): boolean {
299301
return true;
300302
}
301303

304+
/** Ensure a bullet ends with a period. */
305+
function ensurePeriod(bullet: string): string {
306+
const trimmed = bullet.trim();
307+
return trimmed.endsWith('.') ? trimmed : `${trimmed}.`;
308+
}
309+
310+
/** Check if any changed files are in apps/web/. */
311+
function hasWebChanges(files: string[]): boolean {
312+
return files.some(f => f.startsWith('apps/web/'));
313+
}
314+
315+
const DEPLOY_READINESS_BULLET = 'Improved deploy readiness in the web application with clearer onboarding and browser capability detection.'
316+
302317
/** Validate that all bullets pass quality rules. Returns list of failing bullets. */
303318
function validateBullets(bullets: string[]): string[] {
304319
const failures: string[] = [];
@@ -357,8 +372,13 @@ function generateHumanSummary(pr: PRInfo, files: string[], _commits: string): st
357372
}
358373
}
359374

360-
// --- Phase 3: Trim to 3–5 and validate ---
361-
let bullets = candidates.slice(0, 5);
375+
// --- Phase 2b: Inject deploy-readiness bullet if web files changed ---
376+
if (hasWebChanges(files) && !candidates.some(c => c.toLowerCase().includes('deploy readiness'))) {
377+
candidates.push(DEPLOY_READINESS_BULLET);
378+
}
379+
380+
// --- Phase 3: Ensure complete sentences, trim to 3–5 and validate ---
381+
let bullets = candidates.map(ensurePeriod).slice(0, 5);
362382

363383
// Remove any that still fail validation individually
364384
bullets = bullets.filter(b => !isBannedBullet(b) && b.trim().length > 0 && !isTruncatedBullet(b) && isQualityBullet(b));
@@ -380,9 +400,9 @@ function generateHumanSummary(pr: PRInfo, files: string[], _commits: string): st
380400
bullets = buildAreaBullets(files);
381401
// Always ensure at least 3
382402
const fallbacks = [
383-
'Strengthened the export workflow so summaries are cleaner and more reliable',
384-
'Updated documentation to reflect the latest codebase improvements and conventions',
385-
'Improved developer feedback with clearer diagnostics and auto-fix reporting',
403+
'Strengthened the export workflow so summaries are cleaner and more reliable.',
404+
'Updated documentation to reflect the latest codebase improvements and conventions.',
405+
'Improved developer feedback with clearer diagnostics and auto-fix reporting.',
386406
];
387407
for (const fb of fallbacks) {
388408
if (bullets.length >= 3) break;
@@ -392,7 +412,7 @@ function generateHumanSummary(pr: PRInfo, files: string[], _commits: string): st
392412
}
393413
}
394414

395-
return bullets.slice(0, 5);
415+
return bullets.map(ensurePeriod).slice(0, 5);
396416
}
397417

398418
// --- Summary content validation ---
@@ -651,9 +671,9 @@ if (bulletErrors.length > 0) {
651671
humanBullets = buildAreaBullets(milestoneFiles);
652672
// Ensure 3–5 range
653673
const fallbacks = [
654-
'Strengthened the export workflow so summaries are cleaner and more reliable',
655-
'Updated documentation to reflect the latest codebase improvements and conventions',
656-
'Improved developer feedback with clearer diagnostics and auto-fix reporting',
674+
'Strengthened the export workflow so summaries are cleaner and more reliable.',
675+
'Updated documentation to reflect the latest codebase improvements and conventions.',
676+
'Improved developer feedback with clearer diagnostics and auto-fix reporting.',
657677
];
658678
for (const fb of fallbacks) {
659679
if (humanBullets.length >= 3) break;

packages/core/src/config.test.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ import {
66
cliRulesToConfig,
77
} from './config.js';
88
import { allRules } from './rules/index.js';
9+
import { resolvePreset, getPresetNames } from './presets.js';
10+
11+
const ALL_RULE_IDS = [
12+
'unused-imports',
13+
'complexity-hotspot',
14+
'optional-chaining',
15+
'boolean-simplification',
16+
'early-return',
17+
'no-debugger',
18+
'no-empty-catch',
19+
'no-useless-return',
20+
'ts-diagnostics',
21+
];
922

1023
describe('parseConfig', () => {
1124
it('parses a valid config', () => {
@@ -51,6 +64,39 @@ describe('mergeConfig', () => {
5164
});
5265
});
5366

67+
describe('DEFAULT_CONFIG contains all rules', () => {
68+
it('has every registered rule in defaults', () => {
69+
const defaults = mergeConfig(null);
70+
for (const id of ALL_RULE_IDS) {
71+
expect(defaults).toHaveProperty(id);
72+
expect(['error', 'warn', 'off']).toContain(defaults[id]);
73+
}
74+
});
75+
76+
it('rule registry matches expected rule IDs', () => {
77+
const registryIds = allRules.map((r) => r.id).sort();
78+
expect(registryIds).toEqual([...ALL_RULE_IDS].sort());
79+
});
80+
81+
it('no rule exists in registry but not in DEFAULT_CONFIG', () => {
82+
const defaults = mergeConfig(null);
83+
for (const rule of allRules) {
84+
expect(defaults).toHaveProperty(rule.id);
85+
}
86+
});
87+
});
88+
89+
describe('presets produce valid configs', () => {
90+
it.each(getPresetNames())('preset "%s" contains all rule IDs', (presetName) => {
91+
const config = resolvePreset(presetName);
92+
expect(config).not.toBeNull();
93+
for (const id of ALL_RULE_IDS) {
94+
expect(config).toHaveProperty(id);
95+
expect(['error', 'warn', 'off']).toContain(config![id]);
96+
}
97+
});
98+
});
99+
54100
describe('filterRulesByConfig', () => {
55101
it('removes rules set to off', () => {
56102
const config = {
@@ -77,6 +123,18 @@ describe('filterRulesByConfig', () => {
77123
const rule = filtered.find((r) => r.id === 'unused-imports');
78124
expect(rule?.severity).toBe('error');
79125
});
126+
127+
it('returns only active rules from a full config', () => {
128+
const defaults = mergeConfig(null);
129+
const filtered = filterRulesByConfig(allRules, defaults);
130+
// ts-diagnostics is 'off' in defaults, so it should be excluded
131+
expect(filtered.find((r) => r.id === 'ts-diagnostics')).toBeUndefined();
132+
// All other rules should be present
133+
for (const rule of allRules) {
134+
if (rule.id === 'ts-diagnostics') continue;
135+
expect(filtered.find((r) => r.id === rule.id)).toBeDefined();
136+
}
137+
});
80138
});
81139

82140
describe('cliRulesToConfig', () => {
@@ -95,4 +153,13 @@ describe('cliRulesToConfig', () => {
95153
expect(config['early-return']).toBe('warn');
96154
expect(config['unused-imports']).toBe('off');
97155
});
156+
157+
it('sets all rules to off or warn', () => {
158+
const ids = allRules.map((r) => r.id);
159+
const config = cliRulesToConfig('no-debugger', ids);
160+
for (const id of ids) {
161+
expect(['warn', 'off']).toContain(config[id]);
162+
}
163+
expect(config['no-debugger']).toBe('warn');
164+
});
98165
});

0 commit comments

Comments
 (0)