Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
f8d5dcd
Initial plan
Copilot Mar 12, 2026
6618762
install @coderrob/eslint-plugin-zero-tolerance
Copilot Mar 12, 2026
b1c1e3e
add @coderrob/eslint-plugin-zero-tolerance to eslint config and parti…
Copilot Mar 12, 2026
dfdcf5d
fix type check errors introduced by interface renames and invalid Str…
Copilot Mar 12, 2026
ad0741f
fix all lint errors and majority of warnings across source and test f…
Copilot Mar 13, 2026
9082a52
update zero-tolerance to 1.2.2 and fix all new lint warnings and errors
Copilot Apr 4, 2026
6566671
Merge branch 'main' into copilot/install-eslint-plugin-zero-tolerance
Coderrob Apr 4, 2026
c423000
fix export-cache.test.ts: replace getExports with resolveExports
Copilot Apr 4, 2026
6cea287
fix barrel-content.builder: skip undefined entries instead of throwing
Copilot Apr 4, 2026
b5a151f
feat: add support for wildcard exports and enhance export handling
Coderrob Aug 6, 2026
9388fec
feat(parser): refactor ExportParser to improve export extraction and …
Coderrob Aug 7, 2026
478c498
feat: enhance VS Code integration tests and improve concurrency handl…
Coderrob Aug 7, 2026
e4f3194
feat: update CHANGELOG for version 1.1.2 and remove hardening plan do…
Coderrob Aug 7, 2026
51802c1
Remove jscodeshift dependency and delete fix-instanceof-error codemod…
Coderrob Aug 7, 2026
5808775
feat: remove instanceof Error codemod and jscodeshift dependency, upd…
Coderrob Aug 7, 2026
e029b70
feat: update CHANGELOG, improve test coverage, and enhance semaphore …
Coderrob Aug 7, 2026
e0ab5d3
fix: ensure proper SVG formatting in coverage badge
Coderrob Aug 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .dependency-cruiser.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module.exports = {
String.raw`(^|/)webpack\\.config\\.(js|cjs|mjs)$`, // Webpack config
String.raw`(^|/)rollup\\.config\\.(js|cjs|mjs)$`, // Rollup config
String.raw`(^|/)eslint\.config\.(js|cjs|mjs)$`, // ESLint config
String.raw`^src/test/integration/index\.ts$`, // VS Code integration entry point
],
},
to: {},
Expand All @@ -51,7 +52,7 @@ module.exports = {
fileName: 'tsconfig.json',
},
webpackConfig: {
fileName: 'webpack.config.js',
fileName: 'webpack.config.cjs',
},
},
};
12 changes: 7 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [20.x, 22.x]

steps:
- uses: actions/checkout@v4

- name: Use Node.js ${{ matrix.node-version }}
- name: Use Node.js 22
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
node-version: 22.x
cache: 'npm'

- name: Install dependencies
Expand All @@ -47,8 +46,11 @@ jobs:
- name: Compile tests
run: npm run compile-tests

- name: Run unit tests
run: npm test
- name: Run unit tests with per-file coverage
run: npm run coverage:verify

- name: Check for memory retention
run: npm run memory:check

- name: Package extension
run: npm run package
61 changes: 58 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,61 @@ This file documents automation, scripts, CI checks, and packaging conventions us
- Unit test titles must start with `should` (enforced by ESLint).
- Shared test helpers live in `src/test/testTypes.ts`.
- Test runner script: `scripts/run-tests.cjs`.
- Test compilation script: `scripts/run-compile-tests.cjs`; it removes only stale `dist/src` and
`dist/test` compiler outputs before invoking TypeScript so deleted sources cannot affect tests or
coverage.
- Test discovery is glob-based in `dist/test/**` and `dist/src/test/**` to support platform/compiler output differences.
- Test commands:
- `npm test` - compile tests, compile extension, lint, then run tests
- `npm run test:unit` - compile tests, compile extension, then run tests (no lint)
- `npm run test:vscode` - compile tests, run VS Code integration harness
- `npm run test:vscode` - compile tests and the current extension bundle, then run the VS Code
extension-host contract from `dist/src/test/runTest.js`
- `npm run coverage:verify` - run the complete test suite with strict per-file coverage
- `npm run memory:check` - run bounded heap-retention and async-resource checks

### FAST unit tests

All unit tests must follow the FAST principle:

- **Fast:** avoid network access, subprocesses, real timers, and unnecessary compiler or VS Code
startup. Keep stress and heap diagnostics in dedicated scripts rather than the unit suite.
- **Autonomous:** isolate state per test; do not depend on execution order, prior tests, external
services, user configuration, or machine-specific paths.
- **Self-validating:** use deterministic assertions and fail automatically without inspecting logs,
generated reports, or snapshots by hand.
- **Timely:** add or update tests with the behavior they specify, including regression tests for
discovered edge cases.

### Coverage and memory safety

- `npm run coverage:verify` is the canonical coverage gate.
- Every included executable production file must exceed 95% statements, branches, functions, and
lines. Thresholds are configured as 95.01% with c8's per-file enforcement and `all: true`, so
never-loaded runtime modules fail the gate. Exclusions are limited to tests, barrels, declarations,
and compiler-emitted stubs for type-only modules; do not weaken thresholds or exclude executable
production files to make the gate pass.
- `npm run memory:check` is the bounded, offline heap-retention check. It warms up runtime caches,
forces garbage collection between samples, verifies bounded caches release entries, and rejects
retained growth or leaked asynchronous resources.
- Memory stress checks are not unit tests and must remain deterministic and reasonably short.
- The VS Code extension-host test is intentionally separate from the FAST unit suite. It must
activate `coderrob.barrel-roll`, verify contributed command registration, execute barrel
generation through VS Code, and validate the generated file. Do not silently skip this test based
on CI, TTY, or operating-system detection; provide the required display host on headless Linux.

### Defensive, self-describing code

- Validate boundary assumptions before destructive file operations, compiler invocation, resource
accounting, and concurrency setup. Fail with an error that identifies the violated invariant.
- Concurrency helpers must bound both active operations and pending worker promises. Recursive
traversal must preserve one effective file-system concurrency ceiling across sibling directories.
- Name functions and state after observable behavior (`collectFileEntries`, `longLivedParser`) and
document concrete inputs, outputs, and failure conditions; placeholder contract text is not
acceptable.
- Use `ReadonlyMap` and `ReadonlySet` for read-only inputs. When state must change, return a new
collection or make the mutation boundary explicit rather than disguising mutable state as read-only.
- Release temporary parser/compiler resources in `finally` blocks and keep regression tests focused
on public behavior, including ignored, empty, malformed, and failure inputs.

## Packaging and release

Expand All @@ -50,7 +100,11 @@ Verify with `npx @vscode/vsce ls` before publishing.

## CI

CI runs dependency checks and tests. See:
CI runs dependency checks, architectural dependency validation, TypeScript-aware circular/orphan
analysis, duplication checks, per-file coverage, memory-retention checks, and tests. The canonical aggregate quality command is
`npm run quality`; `npm run lint:deps` invokes dependency-cruiser directly.

See:

- `.github/workflows/ci.yml`
- `.github/workflows/release.yml`
Expand All @@ -61,7 +115,8 @@ CI runs dependency checks and tests. See:
npm install
npm run deps:check
npm run lint
npm test
npm run coverage:verify
npm run memory:check
```

## Change discipline
Expand Down
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,54 @@

All notable changes to the "barrel-roll" extension will be documented in this file.

## [1.1.2] - 2026-08-08

### Added

- Support for wildcard, namespace, destructured-binding, `.mts`, and `.cts` exports.
- A real VS Code extension-host contract covering activation, command registration, command
execution, and generated barrel output.
- Strict per-file coverage enforcement above 95%, bounded memory-retention checks, architectural
dependency validation, and the zero-tolerance ESLint ruleset.
- Regression coverage for comment markup, malformed exports, duplicate public names, recursive
traversal, cache eviction, module-specific runtime extensions, legacy wildcard entries,
maximum-depth termination, unreadable source isolation, and file-stat error context.
- Increased verified coverage to 99.86% for statements and lines, 98.22% for branches, and 100% for
functions; barrel generation, file-system operations, and semaphore behavior now have complete
statement, branch, function, and line coverage.

### Changed

- Replaced regex-based barrel inspection with TypeScript AST parsing for export detection and
sanitization.
- Made barrel output deterministic across duplicate named, type-only, default, and wildcard exports.
- Bounded source processing and recursive traversal so active operations and pending worker promises
cannot grow with the complete input set.
- Made barrel content construction a pure transformation using `BarrelEntry.kind`, eliminating
redundant and unbounded file-system probes.
- Simplified semaphore release handling around its non-empty queue invariant, removing an
unreachable fallback branch.
- Updated development dependencies and `@coderrob/eslint-plugin-zero-tolerance` to `1.2.6`.
- Consolidated current automation, testing, coverage, memory, and release guidance in `AGENTS.md`,
`README.md`, and `CONTRIBUTING.md`.

### Fixed

- Preserved type-only default re-exports instead of generating nonexistent runtime default exports.
- Prevented duplicate exports when existing barrels contain multiline declarations, comments,
closing braces in comments, export attributes, or equivalent `/index` paths.
- Corrected VS Code integration-test package-root discovery and isolated inherited Electron test-host
environment variables.
- Preserved direct declarations and standalone comments while removing stale generated re-exports.
- Corrected displaced and placeholder API documentation in the extension and test helpers.

### Removed

- Removed the superseded `hardening.md` planning document; active requirements and useful future work
now live in the maintained project documentation.
- Removed the one-time `instanceof Error` codemod and its `jscodeshift` dependency; the maintained
ESLint autofix remains the supported cleanup path.

## [1.1.1] - 2026-02-19

### Added
Expand Down
21 changes: 18 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,15 @@ Use full validation before submitting:
```bash
npm run lint
npm run deps:check
npm run test
npm run coverage:verify
npm run memory:check
```

## Code style and quality

Run `npm run quality` before submitting changes. It includes formatting and ESLint checks,
dependency-cruiser validation, duplicate-code detection, and TypeScript-aware Madge analysis.

- Language: TypeScript
- Formatter: Prettier (`.prettierrc.json`)
- Lint config: `eslint.config.mjs`
Expand All @@ -58,9 +62,20 @@ npm run test

- Tests live under `src/test/`.
- Test execution uses Node's built-in test runner via `scripts/run-tests.cjs`.
- `npm run test:vscode` compiles the tests and current extension bundle, then launches the real
VS Code-hosted contract. It activates the development extension, checks command registration,
executes barrel generation, and validates its output. The first run may download VS Code;
headless Linux requires a display host such as Xvfb.
- Unit test titles must begin with `should`.
- Keep unit tests FAST: fast, autonomous, self-validating, and timely. Do not put network calls,
subprocesses, real-time waits, or heap stress loops in unit tests.
- Add tests for both success and failure paths.
- Prefer focused unit tests; add integration tests for behavior crossing module boundaries.
- Run `npm run coverage:verify`; every executable production file must exceed 95% for statements, branches,
functions, and lines.
- The test compiler clears stale `dist/src` and `dist/test` output before compiling; do not bypass it
when validating coverage.
- Run `npm run memory:check` for bounded, offline heap-retention and async-resource validation.

## Error handling conventions

Expand All @@ -73,7 +88,6 @@ To clean up ad-hoc error checks:

```bash
npm run lint:fix
npm run fix:instanceof-error
```

## Commit and PR guidance
Expand All @@ -87,7 +101,8 @@ npm run fix:instanceof-error

- [ ] `npm run lint` passes
- [ ] `npm run deps:check` passes
- [ ] `npm test` passes
- [ ] `npm run coverage:verify` passes
- [ ] `npm run memory:check` passes
- [ ] docs updated for command/script/behavior changes
- [ ] changelog updated for user-facing changes

Expand Down
123 changes: 23 additions & 100 deletions IDEAS.md
Original file line number Diff line number Diff line change
@@ -1,111 +1,34 @@
# Ideas & Future Enhancements
# Ideas

This document captures potential improvements and feature ideas for future consideration.
This backlog contains only ideas that would materially improve Barrel Roll's core job: generating
correct, predictable TypeScript barrel files from VS Code.

---
## Configurable exclusion patterns

## 🔮 Proposed Ideas
Allow users to add workspace-specific file and directory exclusions through a
`barrelRoll.exclude` setting. The configured patterns would supplement the safe built-in exclusions
for generated output, dependencies, declarations, and tests.

### Dynamic `.gitignore` Integration
Example:

**Status**: Deferred
**Priority**: Low
**Complexity**: Medium

**Description**:
Instead of relying solely on hardcoded ignored directories, parse `.gitignore` files to dynamically determine which directories to skip during barrel generation.

**Current Approach**:
Hardcoded `IGNORED_DIRECTORIES` set in `src/core/io/file-system.service.ts` covers common cases (node_modules, dist, coverage, etc.).

**Proposed Approach**:

1. Read `.gitignore` at workspace root during barrel generation
1. Extract simple directory names (lines without wildcards, negations, or path separators)
1. Merge with hardcoded defaults

**Implementation Options**:

| Option | Pros | Cons |
| -------------------- | -------------------------------- | ----------------------- |
| Add `ignore` package | Battle-tested, correct semantics | New dependency (~30KB) |
| Simple line matching | Zero dependencies, fast | Misses complex patterns |
| Hybrid approach | Best of both worlds | Partial coverage |

**Sample Implementation** (hybrid):

```typescript
async function loadIgnoredDirectories(workspaceRoot: string): Promise<Set<string>> {
const defaults = new Set([
/* hardcoded list */
]);

try {
const gitignorePath = path.join(workspaceRoot, '.gitignore');
const content = await fs.readFile(gitignorePath, 'utf-8');

for (const line of content.split('\n')) {
const trimmed = line.trim();
// Skip comments, negations, and patterns with wildcards
if (
!trimmed ||
trimmed.startsWith('#') ||
trimmed.startsWith('!') ||
trimmed.includes('*') ||
trimmed.includes('/')
) {
continue;
}
defaults.add(trimmed);
}
} catch {
// No .gitignore or unreadable - use defaults only
}

return defaults;
```json
{
"barrelRoll.exclude": ["**/__fixtures__/**", "**/internal/**", "**/*.generated.ts"]
}
```

**Why Deferred**:
The hardcoded list covers 99% of real-world cases. The overhead of proper `.gitignore` parsing adds complexity and potential maintenance burden without significant user benefit.

**Revisit When**:
This would improve utility for monorepos, generated-code workflows, and projects with private
implementation folders without changing the default behavior.

- Users report missing common directories
- A lightweight, well-maintained gitignore parser becomes available
- Extension gains configuration options for custom ignore patterns
Acceptance criteria:

---
- Support standard workspace-relative glob patterns for files and directories.
- Apply exclusions consistently to single-directory and recursive generation.
- Keep the existing built-in safety exclusions enabled.
- Validate malformed settings and report them through the extension output channel.
- Add contract tests for nested exclusions, file exclusions, Windows paths, and overlapping
patterns.

## ✅ Implemented Ideas

_Ideas that have been implemented will be moved here with a link to the relevant PR or commit._

---

## 📝 How to Add Ideas

Use the following template:

```markdown
### [Idea Title]

**Status**: Proposed | In Progress | Deferred | Rejected
**Priority**: Low | Medium | High
**Complexity**: Low | Medium | High

**Description**:
[What is the idea?]

**Current Approach**:
[How does the extension handle this today?]

**Proposed Approach**:
[How would this idea change things?]

**Why [Status]**:
[Rationale for the current status]

**Revisit When**:
[Conditions that would make this worth reconsidering]
```
Do not infer exclusions from `.gitignore`. Git tracking and public API generation have different
semantics, and partial `.gitignore` support would create surprising behavior. Users who want the
same patterns can add them explicitly to `barrelRoll.exclude`.
Loading
Loading