feat: replace ESLint with Biome and add Lefthook for git hooks#89
feat: replace ESLint with Biome and add Lefthook for git hooks#89galligan wants to merge 5 commits into
Conversation
- Replace ESLint with Biome/Ultracite for TS/JS linting and formatting - Add Lefthook for managing git hooks - Configure markdownlint-cli2 for Markdown formatting - Update all package.json scripts to use new tooling - Update CI workflow to use new linting commands - Remove old ESLint configuration files
- Fix TypeScript strict mode type errors - Update test files for API changes (runMixdownV0 -> runRulesetsV0) - Change parse and lint functions from async to sync - Add Frontmatter type definition for better type safety - Update tests to match new rulesets frontmatter structure - Configure Biome rules to suppress false positives - Fix all formatting and linting issues
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the 📝 WalkthroughSummary by CodeRabbit
WalkthroughReplaces ESLint with Biome/Ultracite and adds Bun/Ultracite tooling, Lefthook hooks and markdownlint-cli2; converts parse and lint APIs from async to synchronous; introduces a Frontmatter type and rulesets structure; CompiledDoc gains a context field; destination processing refactored with per-destination compile/write and directory creation. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor CLI as CLI
participant Core as Core (index.ts)
participant Parser as Parser
participant Linter as Linter
participant Compiler as Compiler
participant Plugin as Destination Plugin
CLI->>Core: runRulesetsV0(path, logger)
Core->>Parser: parse(content) %% synchronous
Parser-->>Core: ParsedDoc
Core->>Linter: lint(ParsedDoc, config) %% synchronous
Linter-->>Core: LintResult[]
Core->>Core: determine destinationIds
loop per destination
Core->>Compiler: compile(ParsedDoc, destinationId, projectConfig)
Compiler-->>Core: CompiledDoc { context: { destinationId, config } }
Core->>Plugin: plugin.write({ compiled, destPath, config, logger })
alt directory missing
Plugin->>Plugin: mkdir -p dir
end
Plugin-->>Core: success / throw
end
Core-->>CLI: done / errors
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
✨ Finishing Touches🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 16
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
packages/core/package.json (1)
20-27: Replace rm -rf with cross‑platform rimraf in build scriptrm -rf is not portable on Windows. Use rimraf.
- "build": "rm -rf dist && tsup && tsc --emitDeclarationOnly", + "build": "rimraf dist && tsup && tsc --emitDeclarationOnly",Add devDependency:
"devDependencies": { + "rimraf": "^6.0.1",CHANGELOG.md (1)
1-19: Document the toolchain migration and add a release headerThe changelog omits the major Biome/Lefthook/markdownlint and CI changes described in the PR. Also add a version/date header for traceability.
Apply something like:
+## [0.1.0] - 2025-09-01 + ### Added - Added `.mix.md` file extension for source rules files to improve discoverability, search capabilities, and IDE support ### Changed +- Replaced ESLint with Biome/Ultracite for linting/formatting +- Added Lefthook-managed git hooks +- Configured markdownlint-cli2 for Markdown formatting +- Updated package.json scripts and CI workflow to new lint commands +- Converted parse/lint APIs from async to sync +- Introduced Frontmatter type and updated frontmatter.rulesets structure +- Updated tests to use runRulesetsV0 and new destinations model - Updated terminology throughout the documentation: - "Mix files" → "Source rules" - "Target" → "Destination" - "Output" → "Compiled rules" - "Track" → "Stem" - "Option" → "Property" - "Snippet" → "Mixin" - `property(value)` → `property-*` and `name-("value")` - Updated directory structure: - `.mixdown/mixes/` → `.mixdown/src/` - `.mixdown/mixes/_snippets/` → `.mixdown/src/_mixins/` - `.mixdown/output/` → `.mixdown/dist/`packages/core/src/linter/__tests__/linter.spec.ts (1)
73-93: Update test name and message for non-object rulesets.
The linter expects an object with version; it reports an invalid declaration, not “field type”.- it("should error when rulesets field is not a string", () => { + it("should error when rulesets field is not an object with version", () => { ... - const typeError = results.find((r) => r.message.includes('Invalid "rulesets" field type')); + const typeError = results.find((r) => + r.message.includes("Invalid Rulesets version declaration") + );
🧹 Nitpick comments (39)
packages/core/tsconfig.json (1)
3-11: Optional: align TS baseline with Bun/Node ESM usage.
- Consider moduleResolution: "NodeNext" (or "Bundler") in base for cleaner ESM/resolution.
- If the repo targets modern runtimes, bump target/lib to ES2022 for built-ins typing.
.markdownlint.json (1)
6-6: Avoid dual-config drift with markdownlint-cli2.If CLI2 is the only runner, drop this file and keep .markdownlint-cli2.yaml as single source of truth.
.biomeignore (1)
1-8: Expand ignores to cover real lockfiles and common artefacts.Biome may scan/format JSON/YAML; add the actual lockfiles and snapshots.
Apply:
node_modules/ dist/ .turbo/ coverage/ -*.lock -bun.lock +.DS_Store +# Lockfiles +*.lock +package-lock.json +pnpm-lock.yaml +yarn.lock +bun.lockb +# Misc .changeset/ docs_archive/ +*.snaptsconfig.base.json (1)
2-16: Modernise moduleResolution and isolate test typings
- In tsconfig.base.json, update
"moduleResolution": "node"→"moduleResolution": "NodeNext"(keep"module": "ESNext").- Remove
"vitest/globals"from the base"types"and add it only in a new per-package test tsconfig (e.g. tsconfig.test.json extending the base) so global test types don’t leak into non-test builds..prettierrc (1)
6-18: Prevent formatter overlap with Biome/markdownlint.
Since Biome now formats TS/JS and markdownlint-cli2 covers Markdown, consider excluding Markdown (and any other Biome-managed types) from Prettier to avoid churn. Verify lefthook/CI don’t run both on the same files.If desired, update .prettierignore to include:
- *.md
- *.mdx
- docs/**
tsconfig.json (1)
1-8: Consider project references and test typechecking.
- Optional: add "composite": true and "references" to packages for faster tsc -b and clearer boundaries.
- Excluding tests here is fine if tests are typechecked elsewhere; confirm there’s a per-package test tsconfig or a CI step that typechecks tests.
.prettierignore (1)
17-19: Ignore Bun’s actual lockfile (bun.lockb), not bun.lockBun uses bun.lockb. Keeping bun.lock is a no-op and bun.lockb might still be processed by Prettier.
*.lock -bun.lock +bun.lockb .changeset/packages/core/vitest.config.ts (1)
7-13: Confirm test runner direction (Vitest vs Bun test)Repo-wide work has been moving to Bun-first. If the intention is to standardise on Bun’s test runner, plan a migration; otherwise ensure CI calls vitest explicitly (not bun test).
packages/core/package.json (1)
24-25: Script naming consistency: prefer format/check over lint:fixElsewhere we’ve standardised on format (writes) and check (CI). Consider aligning.
- "lint": "bunx ultracite lint .", - "lint:fix": "bunx ultracite format .", + "check": "bunx ultracite lint .", + "format": "bunx ultracite format .",If CI expects a specific name (e.g., check:ci), keep it consistent with the workflow.
biome.json (1)
15-16: Include mjs/cjs/mts/cts in Biome file matchesCovers common JS/TS module variants so lint/format applies uniformly.
- "includes": ["**/*.{js,ts,jsx,tsx,json,jsonc}"] + "includes": ["**/*.{js,ts,jsx,tsx,mjs,cjs,mts,cts,json,jsonc}"]README.md (1)
154-155: Header punctuation consistencyMinor: other numbered headings use terminal punctuation variably. Either keep the colon or remove consistently across the section.
-### 3. Find your compiled rules at +### 3. Find your compiled rules at:.markdownlint-cli2.yaml (3)
3-9: Remove duplicate MD013 disablementYou’re disabling line-length twice (MD013 and line-length). Keep one (prefer MD013) to avoid confusion.
MD025: false # Multiple top-level headings - line-length: false
11-23: Deduplicate ignores and add Bun’s lockfileTrim duplicate patterns and ignore Bun’s binary lockfile to avoid accidental checks.
ignores: - - node_modules/** - - "**/node_modules/**" - - dist/** - - "**/dist/**" - - .turbo/** - - "**/.turbo/**" - - coverage/** - - "**/coverage/**" - - "**/*.lock" - - "**/bun.lock" - - .changeset/** - - docs_archive/** + - "**/node_modules/**" + - "**/dist/**" + - "**/.turbo/**" + - "**/coverage/**" + - "**/*.lock" + - "**/bun.lock" + - "**/bun.lockb" + - ".changeset/**" + - "docs_archive/**"
23-23: Add trailing newlineYAMLLint flags missing EOF newline. Add one to satisfy formatters and tools.
.github/actions/setup-bun-and-deps/action.yml (1)
34-41: Use explicit expressions in if: for clarityThe current if: inputs.run-… works, but wrapping in ${{ }} avoids ambiguity and matches GH Actions docs.
- - name: Check Format - if: inputs.run-lint == 'true' + - name: Check Format + if: ${{ inputs.run-lint == 'true' }} run: bun run check:ci shell: bash - - name: Lint Markdown - if: inputs.run-lint == 'true' + - name: Lint Markdown + if: ${{ inputs.run-lint == 'true' }} run: bun run lint:md shell: bash - name: Test - if: inputs.run-test == 'true' + if: ${{ inputs.run-test == 'true' }} run: bun run test shell: bash - name: Build - if: inputs.run-build == 'true' + if: ${{ inputs.run-build == 'true' }} run: bun run build shell: bashAlso applies to: 45-52
packages/core/src/destinations/index.ts (2)
8-11: Avoid side effects at import-time if constructors touch the FS.
IfCursorPlugin/WindsurfPluginconstructors do IO or read config, prefer lazy instantiation to keep module loads cheap and test-friendly.Apply:
-export const cursorPlugin = new CursorPlugin(); -export const windsurfPlugin = new WindsurfPlugin(); +let _singletons: + | { cursor: DestinationPlugin; windsurf: DestinationPlugin } + | undefined; +export const getDestinations = () => { + if (!_singletons) { + _singletons = { + cursor: new CursorPlugin(), + windsurf: new WindsurfPlugin(), + }; + } + return _singletons; +};
13-16: Prefer a typed Record over Map for exhaustiveness and simpler consumption.
A Record with aDestinationIdunion catches missing keys at compile time and is easier to serialise/mock.-export const destinations: ReadonlyMap<string, DestinationPlugin> = new Map([ - ["cursor", cursorPlugin], - ["windsurf", windsurfPlugin], -]); +export type DestinationId = "cursor" | "windsurf"; +export const destinations = { + cursor: new CursorPlugin(), + windsurf: new WindsurfPlugin(), +} as const satisfies Record<DestinationId, DestinationPlugin>;If you keep Map, consider deriving keys from
plugin.idto avoid drift.lefthook.yml (2)
1-12: Prevent formatter races on .md and auto-stage fixes.
Prettier and markdownlint both write to Markdown; running them in parallel can cause non-deterministic results. Also, withoutstage_fixed: true, fixes may not be re-staged.-pre-commit: - parallel: true +pre-commit: + parallel: false + stage_fixed: true commands: ultracite: glob: "**/*.{ts,tsx,js,jsx,json}" run: "bunx ultracite format {staged_files}" - prettier: - glob: "**/*.{md,yml,yaml}" + prettier: + glob: "**/*.{yml,yaml}" run: "bunx prettier --write {staged_files}" markdownlint: glob: "**/*.md" run: "bunx markdownlint-cli2 {staged_files} --fix"Alternatively, keep Prettier on MD but keep
parallel: falseto sequence them deterministically.
14-23: Pre-push gate is sensible. LGTM.
Optional: addtimeouttags if pushes occasionally hang on CI-heavy repos.packages/core/src/parser/__tests__/parser.spec.ts (2)
79-92: Unclosed frontmatter assertion mirrors the previous test—looks good pending line-base check.
104-118: Body preservation assertion is robust. LGTM.
Minor: ifparseexposesbody, asserting exactbodyequality would remove reliance on substring checks.packages/core/src/destinations/cursor-plugin.ts (1)
61-64: Optional: write atomically to avoid partial writesWrite to a temp file and rename to reduce risk of readers observing partial content.
- await fs.writeFile(resolvedPath, compiled.output.content, { encoding: "utf8" }); + const tmpPath = `${resolvedPath}.tmp`; + await fs.writeFile(tmpPath, compiled.output.content, { encoding: "utf8" }); + await fs.rename(tmpPath, resolvedPath);packages/core/src/destinations/windsurf-plugin.ts (1)
61-65: Optional: atomic writes for robustnessMirror the atomic write approach here as well.
- await fs.writeFile(resolvedPath, compiled.output.content, "utf8"); + const tmpPath = `${resolvedPath}.tmp`; + await fs.writeFile(tmpPath, compiled.output.content, "utf8"); + await fs.rename(tmpPath, resolvedPath);packages/core/src/interfaces/frontmatter.ts (1)
7-21: Tighten value types to JSON-safe valuesUse a JsonValue alias instead of unknown to prevent functions/symbols leaking into config.
Add:
export type JsonValue = | string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };Then update the type:
- rulesets?: { - version: string; - [key: string]: unknown; - }; + rulesets?: { + version: string; + [key: string]: JsonValue; + }; @@ - [key: string]: unknown; + [key: string]: JsonValue; } >; - [key: string]: unknown; + [key: string]: JsonValue;packages/core/src/parser/index.ts (3)
9-12: Update JSDoc to reflect synchronous API.Comment still says it returns a Promise.
- * @returns A promise that resolves to a ParsedDoc + * @returns ParsedDoc
17-33: Handle BOM and YAML terminating ellipsis.Improve robustness for UTF-8 BOMs and YAML
...terminator.-export function parse(content: string): ParsedDoc { - const lines = content.split("\n"); +export function parse(content: string): ParsedDoc { + // Normalise potential BOM at start of file + const normalised = content.replace(/^\uFEFF/, ""); + const lines = normalised.split("\n"); @@ - for (let i = 1; i < lines.length; i++) { - if (lines[i].trim() === "---") { + for (let i = 1; i < lines.length; i++) { + const trimmed = lines[i].trim(); + if (trimmed === "---" || trimmed === "...") { frontmatterEnd = i; break; } }Also applies to: 35-38
39-70: Surface precise YAML error location.Use js-yaml’s error.mark to report accurate line/column within frontmatter.
- } catch (error) { - let friendlyMessage = "Invalid YAML syntax in frontmatter. "; + } catch (error) { + let friendlyMessage = "Invalid YAML syntax in frontmatter. "; + const mark = (error as any)?.mark; @@ - errors.push({ - message: friendlyMessage, - line: frontmatterStart + 1, - column: 1, - }); + errors.push({ + message: friendlyMessage, + // error.mark.{line,column} are 0-based and relative to frontmatter + line: typeof mark?.line === "number" ? frontmatterStart + 1 + mark.line : frontmatterStart + 1, + column: typeof mark?.column === "number" ? mark.column + 1 : 1, + });package.json (2)
17-18: Add missing path argument to format:check for consistency.Other Ultracite invocations pass “.”; keep it consistent.
- "format:check": "bunx ultracite lint", + "format:check": "bunx ultracite lint .",
14-19: Deduplicate “lint:fix” aliasing and keep semantics clear.Have lint:fix call format:fix to avoid two sources of truth.
- "lint:fix": "bunx ultracite format .", + "lint:fix": "bun run format:fix",packages/core/tests/integration/e2e.spec.ts (1)
3-6: Optional: migrate to Bun’s test API for consistency.If the repo standardised on Bun tests, switch from Vitest imports to
bun:test.I can provide a mechanical codemod if desired.
packages/core/src/interfaces/destination-plugin.ts (1)
41-47: Make write ctx immutable and future-proof config typing.Avoid accidental mutations and leave room for narrowed config types later.
- write(ctx: { - compiled: CompiledDoc; - destPath: string; - config: Record<string, unknown>; // Validated via schema from configSchema() - logger: Logger; - }): Promise<void>; + write(ctx: Readonly<{ + compiled: CompiledDoc; + destPath: string; + config: Record<string, unknown>; // Validated via schema from configSchema() + logger: Logger; + }>): Promise<void>;packages/core/src/compiler/index.ts (2)
5-13: Fix JSDoc: function is synchronous, not a Promise.
Update the return type in the doc to avoid confusion.- * @returns A promise that resolves to a CompiledDoc + * @returns CompiledDoc
47-51: Preserve body whitespace unless the spec mandates trimming.
Trimming drops intentional leading/trailing blank lines.- .join("\n") - .trim(); + .join("\n");Would you like this normalisation, or should we preserve authoring whitespace?
packages/core/src/linter/index.ts (2)
31-38: Fix JSDoc: function is synchronous.
Update the return description accordingly.- * @returns A promise that resolves to an array of lint results + * @returns LintResult[]
80-87: Validate rulesets.version type as string.
Prevents objects with non-string versions slipping through.- } else if (typeof frontmatter.rulesets !== "object" || frontmatter.rulesets === null || !('version' in frontmatter.rulesets)) { + } else if ( + typeof frontmatter.rulesets !== "object" || + frontmatter.rulesets === null || + !("version" in frontmatter.rulesets) + ) { results.push({ message: `Invalid ${getFieldName("/rulesets")}. Expected object with version property, got ${typeof frontmatter.rulesets}.`, line: 1, column: 1, severity: "error", }); + } else if (typeof (frontmatter.rulesets as any).version !== "string") { + results.push({ + message: `Invalid ${getFieldName("/rulesets/version")}. Expected string, got ${typeof (frontmatter.rulesets as any).version}.`, + line: 1, + column: 1, + severity: "error", + });packages/core/src/interfaces/compiled-doc.ts (2)
56-64: Prefer readonly arrays for AST collectionsThese arrays are part of the parsed/compiled model and shouldn’t be mutated downstream. Making them readonly helps prevent accidental writes and improves type safety.
- ast: { - // Abstract Syntax Tree - minimal for v0 - stems: Stem[]; - imports: Import[]; - variables: Variable[]; - markers: Marker[]; // All markers found - empty for v0 body processing - }; + ast: { + // Abstract Syntax Tree - minimal for v0 + stems: ReadonlyArray<Stem>; + imports: ReadonlyArray<Import>; + variables: ReadonlyArray<Variable>; + markers: ReadonlyArray<Marker>; // All markers found - empty for v0 body processing + };- ast: { - stems: Stem[]; // Array of parsed stems (empty for v0 body) - imports: Import[]; // Array of parsed imports (empty for v0 body) - variables: Variable[]; // Array of parsed variables (empty for v0 body) - markers: Marker[]; // All markers found in the document (empty for v0 body) - }; + ast: { + stems: ReadonlyArray<Stem>; // Array of parsed stems (empty for v0 body) + imports: ReadonlyArray<Import>; // Array of parsed imports (empty for v0 body) + variables: ReadonlyArray<Variable>; // Array of parsed variables (empty for v0 body) + markers: ReadonlyArray<Marker>; // All markers found in the document (empty for v0 body) + };Also applies to: 84-89
97-101: Consider making CompiledDoc generic over configContext config will vary by destination. A generic makes the type more expressive without breaking current usage.
-export type CompiledDoc = { +export type CompiledDoc<TConfig = Record<string, unknown>> = { /** Additional context for the compilation */ context: { destinationId: string; // Current destination being compiled for - config: Record<string, unknown>; // Resolved configuration for this compilation (e.g., project config, destination-specific config) + config: TConfig; // Resolved configuration for this compilation (e.g., project config, destination-specific config) }; };packages/core/src/index.ts (2)
94-108: Make the severity switch exhaustive and observableIf the enum widens, the default path is currently silent. Emit a warning and assert exhaustiveness in TS.
switch (result.severity) { case "error": logger.error(message); hasErrors = true; break; case "warning": logger.warn(message); break; case "info": logger.info(message); break; - default: - // Exhaustive check for LintSeverity type - break; + default: { + // Exhaustive check for LintSeverity type + const _exhaustive: never = result.severity as never; + logger.warn(`Unknown lint severity: ${String(result.severity)}`); + void _exhaustive; + break; + } }
173-186: CJS main-module check is safe
The repository has no"type"field in any package.json (defaults to CommonJS) and tsconfig.json doesn’t specify an ESM module, sorequire.main === moduleworks as expected. If you plan to support ESM execution in the future, you can optionally adopt the cross-runtime guard pattern suggested earlier.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (39)
.biomeignore(1 hunks).changeset/config.json(1 hunks).eslintrc.js(0 hunks).github/actions/setup-bun-and-deps/action.yml(3 hunks).markdownlint-cli2.yaml(1 hunks).markdownlint.json(1 hunks).prettierignore(1 hunks).prettierrc(1 hunks)AGENTS.md(1 hunks)CHANGELOG.md(1 hunks)README.md(3 hunks)biome.json(1 hunks)lefthook.yml(1 hunks)package.json(2 hunks)packages/core/package.json(2 hunks)packages/core/src/compiler/__tests__/compiler.spec.ts(13 hunks)packages/core/src/compiler/index.ts(4 hunks)packages/core/src/destinations/__tests__/cursor-plugin.spec.ts(8 hunks)packages/core/src/destinations/__tests__/windsurf-plugin.spec.ts(9 hunks)packages/core/src/destinations/cursor-plugin.ts(4 hunks)packages/core/src/destinations/index.ts(1 hunks)packages/core/src/destinations/windsurf-plugin.ts(3 hunks)packages/core/src/index.ts(5 hunks)packages/core/src/interfaces/compiled-doc.ts(3 hunks)packages/core/src/interfaces/destination-plugin.ts(2 hunks)packages/core/src/interfaces/frontmatter.ts(1 hunks)packages/core/src/interfaces/index.ts(1 hunks)packages/core/src/interfaces/logger.ts(2 hunks)packages/core/src/linter/__tests__/linter.spec.ts(9 hunks)packages/core/src/linter/index.ts(6 hunks)packages/core/src/parser/__tests__/parser.spec.ts(4 hunks)packages/core/src/parser/index.ts(4 hunks)packages/core/tests/integration/e2e.spec.ts(5 hunks)packages/core/tsconfig.json(1 hunks)packages/core/tsup.config.ts(1 hunks)packages/core/vitest.config.ts(1 hunks)tsconfig.base.json(1 hunks)tsconfig.json(1 hunks)turbo.json(1 hunks)
💤 Files with no reviewable changes (1)
- .eslintrc.js
🧰 Additional context used
🧠 Learnings (61)
📓 Common learnings
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-08-15T18:44:08.632Z
Learning: The user (galligan) successfully implemented all PR review feedback after initial discrepancies were identified, including: version marker format standardization from ruleset-v* to mixd-v* throughout PLAN-rulesets-v0.md, cross-platform build scripts using rimraf in packages/compiler/package.json, accurate package description removing CommonMark claims in root package.json, and proper commit tracking with specific hashes (f27e034 + 9ac6df9).
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-23T01:01:27.260Z
Learning: User galligan successfully implemented comprehensive review feedback for PR #93 Bun-native optimization, systematically addressing all critical and important issues including: complete Turborepo reference removal from documentation and codebase, proper build.mjs error logging with array formatting and null coalescing, bunfig.toml security improvements (disabled auto="fallback", fixed watchExclude, moved telemetry to top-level), package.json script optimization (build:all alias, CI enhancement with test:all), and lefthook ultracite command fix (removed invalid --write flag), achieving -422 lines of legacy code removal while adding +18 lines of focused improvements with zero breaking changes and enhanced security, demonstrating gold standard systematic implementation following established patterns from previous PRs.
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-08-19T17:49:13.493Z
Learning: User galligan provided comprehensive feedback on PR review issues, categorizing them by priority (high/medium/minor) and requesting systematic fixes including cross-platform build compatibility (rimraf instead of rm -rf), test framework alignment (bun:test instead of Jest), documentation-code consistency for directory exclusions, extraction of shared discovery logic to reduce duplication, and proper integration test implementation. Successfully addressed all feedback with complete code solutions.
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-08-26T04:15:29.029Z
Learning: User galligan reported comprehensive fixes for PR #84 critical CodeRabbit feedback including: turbo dependency addition for CI build failure, codex provider addition to sandbox VALID_PROVIDER_TYPES, DEFAULT_CONFIG parallelCompilation property, RegExp lastIndex hazard fixes using matchAll, parallel compilation test logging enhancements, partial cache improvements storing compiled templates, .rule.md extension support for @-partial resolution, clearPartialCache fixes for hbs.partials registry, and silent LogLevel type addition. Verification confirmed extensive codex provider implementation, sophisticated CI quick fix workflow, robust partial cache system, and parallel compilation test infrastructure. Some specific claims require additional verification due to possible branch visibility issues, consistent with galligan's systematic implementation track record across multiple PRs.
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-22T21:25:13.038Z
Learning: User galligan demonstrated exceptional systematic implementation for commit b93dcf8 in PR #90, comprehensively addressing all review feedback with production-grade fixes including: README documentation alignment using proper ≥ symbol matching package.json engines exactly, package.json script semantic corrections (prepare script using 'bun run config:mdlint', format/check distinction with format writing and check verifying), shell script hardening with defaulted parameter expansions for set -u compatibility (${VAR-} pattern), Biome generator architecture improvements with centralized BIOME_SCHEMA_URL constant and Bun subprocess API with 300s timeouts, enhanced error handling with exit codes and command context, SILENCE_BIOME_WARNINGS environment gate for developer experience, and pragmatic schema version strategy maintaining 2.1.4 for base config compatibility while using 2.2.0 for generated configs, showcasing systematic precision with comprehensive verification and documentation quali...
Learnt from: galligan
PR: outfitter-dev/blz#0
File: :0-0
Timestamp: 2025-08-27T17:01:21.600Z
Learning: User galligan successfully implemented comprehensive fixes for all 4 CodeRabbit review comments in PR #43 commit e7da15d, including: defensive error handling replacing unreachable!() with proper anyhow::bail! error message for NotModified on initial fetch, updating message from "Not modified" to "Up-to-date" in update command, adding etag and last_modified fields to FetchResult::NotModified variant for consistent metadata handling, and implementing atomic metadata writes using temp file pattern (.json.tmp) with fs::rename for data integrity, all within a massive 39K+ line initial codebase commit while maintaining production-quality standards.
<!--
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-09-01T17:50:46.629Z
Learning: User galligan successfully implemented comprehensive CodeRabbit and Copilot feedback for PR #88 Bun migration CI/CD workflow, including: eliminating code duplication by creating composite action .github/actions/setup-bun-and-deps/action.yml for reusable setup process, pinning actions to specific SHAs for security (actions/checkout08eba0b, oven-sh/setup-bun735343b, changesets/actione0145ed), fixing bun.lockb filename issue by renaming from bun.lock for proper Bun lockfile format, hardening release job with timeout-minutes: 30, explicit permissions (contents: write, pull-requests: write), and BUN_VERSION environment variable for consistency, and achieving perfect YAML formatting by removing trailing spaces and adding final newline. This demonstrates galligan's continued systematic approach to implementing feedback with production-ready GitHub Actions automation following enterprise-grade technical standards.
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-22T21:25:13.038Z
Learning: Branch visibility issue identified in PR #90 review: verification scripts running on branch "coderabbit_90" with no recent commits visible, explaining why galligan's claimed fixes from commit b93dcf8 were not found during verification. Current state shows pre-fix conditions (README/package.json mismatch, invalid prepare script syntax, swapped format/check semantics, direct $VAR usage in shell), suggesting either different branch contains the fixes, commit not merged to review branch, or push timing issue. This technical issue explains discrepancies without affecting galligan's systematic implementation quality track record.
Learnt from: galligan
PR: outfitter-dev/blz#0
File: :0-0
Timestamp: 2025-08-30T20:13:12.910Z
Learning: User galligan successfully completed the v0.1 release train stack consolidation for Issue #86, achieving: linear stack structure (main → #57 → #76 → #77 → #78 → #79 → #80 → #81 → #65 → #66 → #82 → #68 → #61 → #46 → #58 → #60 → #53), removal of closed PR #84, repositioning of PR #61 after PR #68, resolution of PR #66 merge conflicts, addressing all 21+ CodeRabbit review comments on PR #68 with proper Rust async patterns and MCP protocol updates, and CI workflow configuration fixes. Remaining blockers are 7 clippy warnings, segmentation fault in coverage testing, and dependency validation failures - demonstrating systematic project management and technical execution for complex Graphite stack operations.
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-08-26T04:15:29.029Z
Learning: User galligan successfully implemented comprehensive fixes for all critical CodeRabbit feedback in PR #84 feature consolidation, including: adding missing turbo dependency to fix CI build failure, adding codex provider to sandbox VALID_PROVIDER_TYPES, fixing DEFAULT_CONFIG type annotation with parallelCompilation property, fixing global RegExp lastIndex hazard using matchAll instead of exec, adding missing log statements for parallel compilation tests, fixing partial cache to store compiled templates for better performance, adding .rule.md extension support for @-partial resolution, fixing clearPartialCache to also clear hbs.partials registry, and adding silent to LogLevel type to match runtime usage. All parallel compilation tests now pass and backward compatibility with v0 alias is maintained, demonstrating galligan's continued systematic approach to implementing feedback with enterprise-grade technical standards.
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: packages/fieldguides/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:13:30.555Z
Learning: Applies to packages/fieldguides/**/*.md : Always lint markdown files with markdownlint-cli2 and fix issues before committing
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-14T03:51:26.625Z
Learning: Applies to **/*.{md,mix.md,mdc} : Markdown files must pass standard markdown-lint without hacks
Learnt from: galligan
PR: outfitter-dev/blz#0
File: :0-0
Timestamp: 2025-08-31T14:18:47.842Z
Learning: User galligan correctly pointed out that after modifying commits, CodeRabbit's memory may become outdated. The files were reorganized from .agents/rules/ directly to .agents/rules/conventions/rust/ subdirectory, and the primary documentation moved from CLAUDE.md to AGENTS.md files. All technical fixes (async-patterns handle.await??, compiler-loop.md jq -sr usage, agent-check.sh permissions and jq usage, storage layout documentation, MCP protocol version 2024-11-05) were properly implemented despite the file structure changes.
📚 Learning: 2025-08-15T16:42:04.468Z
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-15T16:42:04.468Z
Learning: The user (galligan) successfully implemented comprehensive fixes addressing critical configuration issues in biome.json (globals format, files configuration), bunfig.toml (exact setting), and VS Code settings (removing invalid multi-language overrides), while also resolving documentation contradictions and ensuring Ultracite preset compatibility over strict Biome 2.2.0 schema compliance.
Applied to files:
biome.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to **/*.test.@(ts|tsx|js|jsx) : Write tests using Bun’s test API: `import { test, expect } from "bun:test"`; do not use Jest or Vitest APIs
Applied to files:
biome.jsonpackages/core/package.jsonpackages/core/tests/integration/e2e.spec.tspackages/core/vitest.config.ts
📚 Learning: 2025-08-18T18:14:06.160Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: shared/configs/changeset/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:14:06.160Z
Learning: Applies to shared/configs/changeset/**/package.json : Ensure package.json includes Changesets scripts: changeset, changeset:version, and changeset:publish
Applied to files:
.changeset/config.json
📚 Learning: 2025-08-18T18:12:19.906Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: packages/cli/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:12:19.906Z
Learning: Applies to packages/cli/**/tsconfig.json : TypeScript config uses ES modules with target ES2022, module ES2022, and outDir set to ./dist
Applied to files:
packages/core/tsconfig.jsontsconfig.jsonpackages/core/tsup.config.tstsconfig.base.json
📚 Learning: 2025-08-18T18:14:06.160Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: shared/configs/changeset/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:14:06.160Z
Learning: Applies to shared/configs/changeset/**/{tsup.config.ts,tsup.config.js,package.json} : Use tsup to build both CJS and ESM outputs, include TypeScript declarations, and generate source maps
Applied to files:
packages/core/tsconfig.jsontsconfig.jsonpackages/core/tsup.config.ts.prettierignorepackages/core/package.jsontsconfig.base.json
📚 Learning: 2025-08-24T11:27:06.182Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T11:27:06.182Z
Learning: Applies to {tsconfig.json,packages/**/tsconfig.json} : Enable TypeScript strict mode
Applied to files:
tsconfig.json
📚 Learning: 2025-08-14T03:50:36.782Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-14T03:50:36.782Z
Learning: Applies to **/tsconfig*.json : Use strict TypeScript settings
Applied to files:
tsconfig.jsontsconfig.base.json
📚 Learning: 2025-08-24T11:27:39.408Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: AGENT.md:0-0
Timestamp: 2025-08-24T11:27:39.408Z
Learning: Applies to **/tsconfig*.json : Enable TypeScript strict mode in tsconfig
Applied to files:
tsconfig.json
📚 Learning: 2025-08-24T11:27:06.182Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T11:27:06.182Z
Learning: Applies to tsconfig.json : Root tsconfig.json must define project references for all packages (including packages/typescript-config and packages/contracts/ts)
Applied to files:
tsconfig.json
📚 Learning: 2025-08-18T18:10:42.517Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-18T18:10:42.517Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Don't export empty modules that don't change anything
Applied to files:
tsconfig.json
📚 Learning: 2025-08-18T18:14:06.160Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: shared/configs/changeset/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:14:06.160Z
Learning: Applies to shared/configs/changeset/**/package.json : Ensure package.json includes scripts: build, dev, and typecheck (invoked via pnpm)
Applied to files:
tsconfig.jsonpackages/core/package.jsonpackage.json
📚 Learning: 2025-08-18T18:10:42.517Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-18T18:10:42.517Z
Learning: Applies to **/*.{ts,tsx} : Don't use TypeScript namespaces
Applied to files:
tsconfig.json
📚 Learning: 2025-08-18T18:12:55.183Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: packages/contracts/ts/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:12:55.183Z
Learning: Applies to packages/contracts/ts/**/__tests__/**/*.test.ts : Place core tests in standard __tests__ directories using .test.ts files.
Applied to files:
tsconfig.jsonpackages/core/tests/integration/e2e.spec.tspackages/core/vitest.config.ts
📚 Learning: 2025-08-18T18:10:42.517Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-18T18:10:42.517Z
Learning: Applies to **/*.{ts,tsx} : Use either `T[]` or `Array<T>` consistently
Applied to files:
packages/core/tsup.config.ts
📚 Learning: 2025-08-18T18:17:07.077Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-08-18T18:17:07.077Z
Learning: Applies to **/*.{ts,tsx} : Use Array<T> over T[] for array types
Applied to files:
packages/core/tsup.config.ts
📚 Learning: 2025-08-24T11:27:39.408Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: AGENT.md:0-0
Timestamp: 2025-08-24T11:27:39.408Z
Learning: Applies to **/*.{ts,tsx} : Prefer Array<T> over T[]
Applied to files:
packages/core/tsup.config.ts
📚 Learning: 2025-08-14T03:50:36.782Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-14T03:50:36.782Z
Learning: Applies to **/*.ts : Mark environment-dependent behavior with mixd-config
Applied to files:
packages/core/tsup.config.ts
📚 Learning: 2025-08-18T18:14:06.160Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: shared/configs/changeset/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:14:06.160Z
Learning: Applies to shared/configs/changeset/src/index.ts : Keep the main entry point at src/index.ts for this package
Applied to files:
packages/core/tsup.config.ts
📚 Learning: 2025-08-24T11:27:06.182Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T11:27:06.182Z
Learning: Build both CJS and ESM formats for packages
Applied to files:
packages/core/tsup.config.ts
📚 Learning: 2025-08-14T03:50:36.782Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-14T03:50:36.782Z
Learning: Before submitting, run pnpm turbo lint && pnpm turbo test && pnpm turbo build
Applied to files:
.biomeignorepackage.json
📚 Learning: 2025-08-18T18:13:30.555Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: packages/fieldguides/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:13:30.555Z
Learning: Applies to packages/fieldguides/**/*.md : Always lint markdown files with markdownlint-cli2 and fix issues before committing
Applied to files:
.markdownlint-cli2.yaml.markdownlint.json
📚 Learning: 2025-08-14T03:51:26.625Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-14T03:51:26.625Z
Learning: Applies to **/*.{md,mix.md,mdc} : Markdown files must pass standard markdown-lint without hacks
Applied to files:
.markdownlint-cli2.yaml.prettierignore.markdownlint.json
📚 Learning: 2025-08-29T20:55:19.549Z
Learnt from: CR
PR: outfitter-dev/blz#0
File: docs/AGENTS.md:0-0
Timestamp: 2025-08-29T20:55:19.549Z
Learning: Applies to docs/**/*.{md,mdx} : When writing docs, follow the ./.agents/rules/STYLEGUIDE.md
Applied to files:
.markdownlint-cli2.yamlAGENTS.md
📚 Learning: 2025-08-14T03:50:36.782Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-14T03:50:36.782Z
Learning: Applies to **/*.ts : Start each TypeScript file with a TLDR file-purpose comment including the version marker, e.g., // TLDR: File purpose description (mixd-v0)
Applied to files:
packages/core/src/interfaces/frontmatter.ts
📚 Learning: 2025-08-18T18:10:42.517Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-18T18:10:42.517Z
Learning: Applies to **/*.{test,spec}.{js,jsx,ts,tsx} : Ensure assertion functions (like expect) are placed inside an it() call
Applied to files:
packages/core/src/compiler/__tests__/compiler.spec.tspackages/core/src/parser/__tests__/parser.spec.tspackages/core/tests/integration/e2e.spec.tspackages/core/src/linter/__tests__/linter.spec.tspackages/core/src/destinations/__tests__/cursor-plugin.spec.ts
📚 Learning: 2025-08-18T18:17:07.077Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-08-18T18:17:07.077Z
Learning: Applies to **/*.{test,spec}.{js,jsx,ts,tsx} : Ensure the assertion function (e.g., expect) is inside an it() call
Applied to files:
packages/core/src/compiler/__tests__/compiler.spec.tspackages/core/tests/integration/e2e.spec.tspackages/core/src/linter/__tests__/linter.spec.ts
📚 Learning: 2025-08-14T03:51:26.625Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-14T03:51:26.625Z
Learning: Applies to .mixdown/src/**/*.{mix.md,md} : Author source rules in Mixdown Markdown using .mix.md (preferred) or .md extensions
Applied to files:
packages/core/src/compiler/__tests__/compiler.spec.tsCHANGELOG.mdREADME.mdpackages/core/tests/integration/e2e.spec.tspackages/core/src/index.ts
📚 Learning: 2025-08-14T03:51:26.625Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-14T03:51:26.625Z
Learning: Applies to .mixdown/src/**/*.mix.md : Name source rules files in kebab-case with .mix.md extension (e.g., coding-standards.mix.md)
Applied to files:
packages/core/src/compiler/__tests__/compiler.spec.tsCHANGELOG.mdpackages/core/src/index.ts
📚 Learning: 2025-08-14T03:51:26.625Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-14T03:51:26.625Z
Learning: Applies to .mixdown/src/**/*.{mix.md,md} : Write mixes using Markdown ATX-style headers and proper fenced code blocks with language identifiers
Applied to files:
packages/core/src/compiler/__tests__/compiler.spec.tsCHANGELOG.mdREADME.md
📚 Learning: 2025-08-14T03:51:26.625Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-14T03:51:26.625Z
Learning: Applies to .mixdown/mixdown.config.json : Place the Mixdown configuration at .mixdown/mixdown.config.json (kebab-case.config.json)
Applied to files:
packages/core/src/compiler/__tests__/compiler.spec.ts
📚 Learning: 2025-08-14T03:51:26.625Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-14T03:51:26.625Z
Learning: Use mixd-* markers in code comments for version tracking (e.g., // TLDR: ... (mixd-v0))
Applied to files:
packages/core/src/compiler/__tests__/compiler.spec.tsCHANGELOG.md
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Do not import or configure `dotenv`; Bun auto-loads .env files
Applied to files:
.prettierignore
📚 Learning: 2025-08-18T18:10:42.517Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-18T18:10:42.517Z
Learning: Applies to **/*.{ts,tsx} : Don't use the TypeScript directive ts-ignore
Applied to files:
.prettierignore
📚 Learning: 2025-08-31T14:18:47.842Z
Learnt from: galligan
PR: outfitter-dev/blz#0
File: :0-0
Timestamp: 2025-08-31T14:18:47.842Z
Learning: User galligan correctly pointed out that after modifying commits, CodeRabbit's memory may become outdated. The files were reorganized from .agents/rules/ directly to .agents/rules/conventions/rust/ subdirectory, and the primary documentation moved from CLAUDE.md to AGENTS.md files. All technical fixes (async-patterns handle.await??, compiler-loop.md jq -sr usage, agent-check.sh permissions and jq usage, storage layout documentation, MCP protocol version 2024-11-05) were properly implemented despite the file structure changes.
Applied to files:
AGENTS.mdREADME.md
📚 Learning: 2025-08-29T20:27:03.108Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T20:27:03.108Z
Learning: Regularly consult docs: docs/project/GREPABLE.md, docs/project/LANGUAGE.md, docs/project/plans/PLAN-mixdown-v0.md, CLAUDE.md, docs/agentic/**
Applied to files:
AGENTS.md
📚 Learning: 2025-06-23T12:39:16.491Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: packages/fieldguides/docs/CLAUDE.md:0-0
Timestamp: 2025-06-23T12:39:16.491Z
Learning: When writing internal documentation for Agent Outfitter in the docs directory, adopt an enthusiastic and exploratory tone, using adventure metaphors and focusing on equipping agents for their journeys.
Applied to files:
AGENTS.md
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to package.json : Use `bun <file>` (or `bun --hot`) for direct script execution instead of `node` or `ts-node` in scripts
Applied to files:
packages/core/package.jsonpackage.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to package.json : Use `bun build <file.html|file.ts|file.css>` for build scripts instead of webpack or esbuild
Applied to files:
packages/core/package.jsonpackage.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to package.json : Use `bun test` to run tests instead of `jest` or `vitest` in scripts
Applied to files:
packages/core/package.jsonpackage.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run`, `yarn run`, or `pnpm run` in package.json scripts
Applied to files:
packages/core/package.json.github/actions/setup-bun-and-deps/action.yml
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to package.json : Avoid Vite scripts/dependencies; use Bun’s HTML imports and bundler instead
Applied to files:
packages/core/package.jsonpackage.json
📚 Learning: 2025-08-18T18:14:06.160Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: shared/configs/changeset/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:14:06.160Z
Learning: Applies to shared/configs/changeset/src/index.ts : addChangesetScripts must add the scripts: changeset, changeset:version, and changeset:publish to package.json
Applied to files:
packages/core/package.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` for running shell commands instead of `execa`
Applied to files:
packages/core/package.jsonpackage.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to **/esbuild*.@(js|ts|mjs|cjs) : Do not use esbuild; prefer `bun build`
Applied to files:
packages/core/package.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to **/webpack.config.@(js|ts|mjs|cjs) : Do not use webpack; prefer `bun build`
Applied to files:
packages/core/package.json
📚 Learning: 2025-08-14T03:50:36.782Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-14T03:50:36.782Z
Learning: Applies to **/*.ts : Mark API changes or deprecations with mixd-api
Applied to files:
CHANGELOG.mdpackages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-29T20:27:03.108Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T20:27:03.108Z
Learning: Applies to **/*.ts : Use version markers in code: mixd-v{version} (e.g., mixd-v0)
Applied to files:
CHANGELOG.md
📚 Learning: 2025-08-22T21:25:13.038Z
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-22T21:25:13.038Z
Learning: Verification revealed discrepancies between galligan's claimed fixes for PR #90 commit b93dcf8 and actual file contents: README still shows "Node.js 20+ LTS" vs package.json ">=20" (not aligned), prepare script still contains invalid "bun config:mdlint" syntax (missing run keyword), format/check script semantics remain swapped with format using lint and check using format, shell parameter expansion safety patterns ${VAR-} not found in setup.sh, and Biome generator enhancements not visible via grep patterns, suggesting either commit not pushed, wrong branch being verified, or fixes not actually implemented despite detailed documentation claiming completion.
Applied to files:
package.json
📚 Learning: 2025-08-29T20:27:03.108Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T20:27:03.108Z
Learning: Run pnpm turbo lint, typecheck, build, and test before submitting; all must pass
Applied to files:
package.json
📚 Learning: 2025-06-22T11:43:29.772Z
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-06-22T11:43:29.772Z
Learning: TypeScript NodeNext module resolution requires explicit re-exports in packages/contracts/typescript/src/index.ts to make internal symbols visible to external consumers, not just wildcard re-exports.
Applied to files:
packages/core/src/interfaces/index.ts
📚 Learning: 2025-09-01T17:50:46.629Z
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-09-01T17:50:46.629Z
Learning: User galligan successfully implemented comprehensive feedback for PR #88 Bun migration CI/CD workflow, creating enterprise-grade GitHub Actions automation including: sophisticated composite action ./.github/actions/setup-bun-and-deps/action.yml with conditional execution (run-lint/test/build inputs), security hardening with SHA-pinned actions (actions/checkout08eba0b, oven-sh/setup-bun735343b, changesets/actione0145ed), proper bun.lockb file management (113KB) replacing old bun.lock, production-ready release job with timeout-minutes: 30, explicit permissions (contents: write, pull-requests: write), consistent BUN_VERSION: 1.2.21 environment variable, and perfect YAML formatting with zero trailing spaces and proper EOF newlines. This demonstrates galligan's continued systematic approach to implementing feedback with gold standard technical excellence and comprehensive verification.
Applied to files:
.github/actions/setup-bun-and-deps/action.yml
📚 Learning: 2025-09-01T17:50:46.629Z
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-09-01T17:50:46.629Z
Learning: User galligan successfully implemented comprehensive CodeRabbit and Copilot feedback for PR #88 Bun migration CI/CD workflow, including: eliminating code duplication by creating composite action .github/actions/setup-bun-and-deps/action.yml for reusable setup process, pinning actions to specific SHAs for security (actions/checkout08eba0b, oven-sh/setup-bun735343b, changesets/actione0145ed), fixing bun.lockb filename issue by renaming from bun.lock for proper Bun lockfile format, hardening release job with timeout-minutes: 30, explicit permissions (contents: write, pull-requests: write), and BUN_VERSION environment variable for consistency, and achieving perfect YAML formatting by removing trailing spaces and adding final newline. This demonstrates galligan's continued systematic approach to implementing feedback with production-ready GitHub Actions automation following enterprise-grade technical standards.
Applied to files:
.github/actions/setup-bun-and-deps/action.yml
📚 Learning: 2025-08-24T11:27:06.182Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T11:27:06.182Z
Learning: Always use Bun (not npm/yarn/pnpm) for installs, scripts, and updates
Applied to files:
.github/actions/setup-bun-and-deps/action.yml
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Default to using Bun instead of Node.js for running, testing, building, and serving applications
Applied to files:
.github/actions/setup-bun-and-deps/action.yml
📚 Learning: 2025-08-29T20:27:03.108Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T20:27:03.108Z
Learning: Applies to **/*.ts : Use API markers: mixd-api for breaking changes or deprecated functionality
Applied to files:
packages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-24T11:27:06.182Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T11:27:06.182Z
Learning: Applies to packages/**/src/__tests__/**/*.test.{ts,tsx} : Place unit tests under src/__tests__ and name them *.test.ts(x) (Vitest)
Applied to files:
packages/core/tests/integration/e2e.spec.tspackages/core/vitest.config.ts
📚 Learning: 2025-08-18T18:12:55.183Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: packages/contracts/ts/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:12:55.183Z
Learning: Applies to packages/contracts/ts/**/*.test.ts : Create dedicated test files for sub-path entry points (e.g., zod-specific tests) to isolate dependency-aware logic.
Applied to files:
packages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-18T18:10:42.517Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-18T18:10:42.517Z
Learning: Applies to **/*.{test,spec}.{js,jsx,ts,tsx} : Don't nest describe() blocks too deeply in test files
Applied to files:
packages/core/tests/integration/e2e.spec.tspackages/core/src/destinations/__tests__/cursor-plugin.spec.ts
📚 Learning: 2025-08-18T18:17:07.077Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-08-18T18:17:07.077Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't nest describe() blocks too deeply in test files
Applied to files:
packages/core/tests/integration/e2e.spec.tspackages/core/src/destinations/__tests__/cursor-plugin.spec.ts
📚 Learning: 2025-08-18T18:10:42.517Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-18T18:10:42.517Z
Learning: Applies to **/*.{test,spec}.{js,jsx,ts,tsx} : Don't have duplicate hooks in describe blocks
Applied to files:
packages/core/src/destinations/__tests__/cursor-plugin.spec.ts
🪛 YAMLlint (1.37.1)
lefthook.yml
[error] 23-23: no new line character at the end of file
(new-line-at-end-of-file)
.markdownlint-cli2.yaml
[error] 23-23: no new line character at the end of file
(new-line-at-end-of-file)
| run: "bun run typecheck" | ||
| test: | ||
| tags: [optional] | ||
| run: "bun run test" No newline at end of file |
There was a problem hiding this comment.
Add trailing newline to satisfy linters.
[new-line-at-end-of-file]
- run: "bun run test"
+ run: "bun run test"
+📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| run: "bun run test" | |
| run: "bun run test" | |
🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 23-23: no new line character at the end of file
(new-line-at-end-of-file)
🤖 Prompt for AI Agents
In lefthook.yml around line 23, the file is missing a trailing newline which
some linters require; add a single newline character at the end of the file so
the final line (run: "bun run test") is terminated by a newline. Ensure the file
ends with exactly one newline and save the file.
| "check": "bunx ultracite format .", | ||
| "check:ci": "bunx ultracite lint .", | ||
| "check:all": "bun run format && bun run lint && bun run lint:md && bun run typecheck", | ||
| "ci": "bun run format && bun run lint && bun run lint:md && bun run typecheck && bun test", | ||
| "changeset": "changeset", |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Avoid writes in “check” and ensure CI runs workspace tests.
- “check” currently formats (writes). Checks should be read-only.
- “ci” uses
bun testwhich will not run workspace tests via Turbo.
- "check": "bunx ultracite format .",
- "check:ci": "bunx ultracite lint .",
- "check:all": "bun run format && bun run lint && bun run lint:md && bun run typecheck",
- "ci": "bun run format && bun run lint && bun run lint:md && bun run typecheck && bun test",
+ "check": "bun run format:check && bun run lint && bun run lint:md && bun run typecheck",
+ "check:ci": "bunx ultracite lint .",
+ "check:all": "bun run format:check && bun run lint && bun run lint:md && bun run typecheck",
+ "ci": "bun run format && bun run lint && bun run lint:md && bun run typecheck && bun run test",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "check": "bunx ultracite format .", | |
| "check:ci": "bunx ultracite lint .", | |
| "check:all": "bun run format && bun run lint && bun run lint:md && bun run typecheck", | |
| "ci": "bun run format && bun run lint && bun run lint:md && bun run typecheck && bun test", | |
| "changeset": "changeset", | |
| "check": "bun run format:check && bun run lint && bun run lint:md && bun run typecheck", | |
| "check:ci": "bunx ultracite lint .", | |
| "check:all": "bun run format:check && bun run lint && bun run lint:md && bun run typecheck", | |
| "ci": "bun run format && bun run lint && bun run lint:md && bun run typecheck && bun run test", | |
| "changeset": "changeset", |
🤖 Prompt for AI Agents
package.json lines 21-25: The "check" script runs a formatter that writes files
and should be read-only, and the "ci" script invokes `bun test` which doesn't
execute workspace tests via Turbo; change "check" to run the formatter in check
mode (e.g., add the formatter's --check/--list-different flag) so it only
reports differences, and update "ci" to run workspace tests through Turbo (e.g.,
invoke turbo run test or bunx turbo run test) instead of direct `bun test` so
all workspace packages' tests run in CI.
| const result = parse(content); | ||
|
|
||
| expect(result.source.content).toBe(content); | ||
| expect(result.source.frontmatter).toEqual({ | ||
| mixdown: 'v0', | ||
| title: 'Test Rule', | ||
| mixdown: "v0", | ||
| title: "Test Rule", | ||
| destinations: { | ||
| cursor: { | ||
| path: '.cursor/rules/test.mdc', | ||
| path: ".cursor/rules/test.mdc", | ||
| }, | ||
| }, | ||
| }); |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Verify frontmatter key naming matches the new Frontmatter type.
You assert mixdown: "v0". Double-check the canonical field name in Frontmatter (e.g., rulesets vs mixdown) to avoid future drift.
Run:
If the canonical key differs, update the fixture accordingly.
🏁 Script executed:
#!/bin/bash
rg -nP --type=ts -C2 '\b(interface|type)\s+Frontmatter\b' packages/core/src/interfaces
rg -nP -C2 '\bmixdown\b|\brulesets\b' packages/coreLength of output: 19287
Replace mixdown with rulesets.version in frontmatter fixture
Update packages/core/src/parser/__tests__/parser.spec.ts (lines 20–31) to assert
frontmatter: {
rulesets: { version: "v0" },
title: "Test Rule",
destinations: { … }
}
instead of using mixdown: "v0".
🤖 Prompt for AI Agents
In packages/core/src/parser/__tests__/parser.spec.ts around lines 20 to 31, the
test fixture asserts frontmatter using the deprecated key mixdown: "v0"; update
the assertion to replace that key with a nested rulesets.version field. Change
the expected frontmatter object to include rulesets: { version: "v0" } while
keeping title and destinations unchanged, ensuring the test checks
result.source.frontmatter.rulesets.version === "v0" instead of mixdown.
- Update cursor plugin to expect { encoding: 'utf8' } object instead of 'utf-8' string
- Update windsurf plugin to expect 'utf8' string instead of 'utf-8' string
- Update default paths from .mixdown/dist/ to .rulesets/dist/
- Fix node:fs mocking in test files
- Update success log message expectation
37b3cb0 to
ac40457
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Codex Review: Here are some suggestions.
Reply with @codex fix comments to fix any unresolved comments.
About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you open a pull request for review, mark a draft as ready, or comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex fix this CI failure" or "@codex address that feedback".
| private createTransport(): pino.TransportTargetOptions | undefined { | ||
| if (process.env.RULESETS_LOG_PRETTY !== "true") { | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| // Check if pino-pretty is available | ||
| require.resolve("pino-pretty"); |
There was a problem hiding this comment.
[P1] Use of require breaks ESM when pretty logging enabled
The new PinoLogger calls require.resolve("pino-pretty") inside createTransport. This runs whenever RULESETS_LOG_PRETTY is set to "true". However, the package ships an ESM build (tsup outputs an .mjs bundle) where require is not defined. In that case new PinoLogger() throws a ReferenceError before logging can start, so enabling pretty logging crashes instead of gracefully falling back. Consider using createRequire(import.meta.url) or a dynamic import() to probe for pino-pretty so the ESM build can run without errors.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/core/package.json (1)
1-48: Remove lingering ESLint references in documentation
- Update or remove all ESLint mentions in the docs (e.g. docs/project/** and docs/plugins/**) so they reflect the post-migration tooling.
packages/core/src/linter/index.ts (1)
31-38: Fix JSDoc: function is synchronous (no Promise).Return type is now sync; update the docs accordingly and align the version note.
/** * Lints a parsed Rulesets document by validating its frontmatter. - * For v0.1.0, this performs basic schema validation on the frontmatter. + * For v0, this performs basic schema validation on the frontmatter. * * @param parsedDoc - The parsed document to lint * @param config - Optional linter configuration - * @returns A promise that resolves to an array of lint results + * @returns An array of lint results */
♻️ Duplicate comments (3)
packages/core/tests/integration/e2e.spec.ts (1)
9-15: Nice fix: mock the correct module specifier.Switching to vi.mock("node:fs", …) resolves the prior issue.
packages/core/src/linter/__tests__/linter.spec.ts (1)
66-72: Past feedback applied: updated assertion string.Assertion now targets “Missing required Rulesets version declaration”. Looks good.
packages/core/src/compiler/index.ts (1)
38-44: Frontmatter delimiter detection is now CRLF-safe — nice.This addresses the prior feedback to trim and split with /\r?\n/.
🧹 Nitpick comments (21)
CHANGELOG.md (1)
1-1: Add compare/reference links for Keep a Changelog consistencyAppend link refs for [0.1.0] (e.g., compare main...v0.1.0) at file end for easy navigation.
## [0.1.0] - 2025-09-01 + +<!-- Links --> +[0.1.0]: https://github.com/outfitter-dev/rulesets/compare/prev-tag...v0.1.0packages/core/package.json (2)
24-25: Minor: unify lint script naming to reduce cognitive loadBoth “lint” (checks) and “lint:fix” (formats) are fine, but consider aligning names with root (format vs lint) to avoid overlap.
28-31: Optional: mark package as side‑effect free for better tree‑shakingAdd sideEffects:false if the bundle is pure on import (appears so).
"files": [ "dist" ], + "sideEffects": false,Also applies to: 36-43
package.json (2)
21-24: Avoid duplicate work in “check” pipeline“check” and “check:all” re-run lint via format:check (which equals lint) and then lint again. Drop the first call to de-duplicate.
- "check": "bun run format:check && bun run lint && bun run lint:md && bun run typecheck", + "check": "bun run lint && bun run lint:md && bun run typecheck", - "check:all": "bun run format:check && bun run lint && bun run lint:md && bun run typecheck", + "check:all": "bun run lint && bun run lint:md && bun run typecheck",
24-24: CI should not write filesRunning “format” in CI writes; prefer read‑only checks.
- "ci": "bun run format && bun run lint && bun run lint:md && bun run typecheck && bun run test", + "ci": "bun run lint && bun run lint:md && bun run typecheck && bun run test",packages/core/src/interfaces/logger.ts (2)
110-129: ESM-safe pino-pretty detectionrequire.resolve can throw ReferenceError in ESM; use createRequire for robust resolution while keeping the graceful fallback.
-import pino from "pino"; +import pino from "pino"; +import { createRequire } from "node:module"; @@ private createTransport(): pino.TransportTargetOptions | undefined { if (process.env.RULESETS_LOG_PRETTY !== "true") { return; } try { - // Check if pino-pretty is available - require.resolve("pino-pretty"); + // Check if pino-pretty is available (ESM-safe) + const req = createRequire(import.meta.url); + req.resolve("pino-pretty"); return { target: "pino-pretty", options: { colorize: true, ignore: "pid,hostname", translateTime: "SYS:standard", }, }; } catch { // pino-pretty not available, fall back to default transport return; } }Also applies to: 3-3
5-6: Consider aligning levels with Pino’s full setIf you want environment parity with Pino, include “trace” and “fatal” in LogLevel and ordering.
-export type LogLevel = "debug" | "info" | "warn" | "error"; +export type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal"; @@ - const validLevels: LogLevel[] = ["debug", "info", "warn", "error"]; + const validLevels: LogLevel[] = ["trace", "debug", "info", "warn", "error", "fatal"]; @@ - const levels: LogLevel[] = ["debug", "info", "warn", "error"]; + const levels: LogLevel[] = ["trace", "debug", "info", "warn", "error", "fatal"];Also applies to: 24-27, 31-35
packages/core/src/destinations/cursor-plugin.ts (1)
3-5: Minor: prefer named import for path in TS without esModuleInteropIf tsconfig disables synthetic default imports, switch to
import * as path from "node:path".-import path from "node:path"; +import * as path from "node:path";packages/core/src/interfaces/__tests__/logger.spec.ts (2)
1-2: Drop hard-coded version in header.Avoid embedding version (“v0.2.0”) in test comments; it drifts. Keep a single, generic header.
Apply:
-// :M: tldr: Tests for Logger interface implementations -// :M: v0.2.0: Tests for both ConsoleLogger and PinoLogger implementations +// Tests for Logger interface implementations (ConsoleLogger + PinoLogger)
13-16: Use spies instead of reassigning global console.Directly overwriting console methods is brittle; prefer vi.spyOn and drop manual restores.
Apply:
-const originalConsoleDebug = console.debug; -const originalConsoleInfo = console.info; -const originalConsoleWarn = console.warn; -const originalConsoleError = console.error; +// originals not needed when using spies beforeEach(() => { - console.debug = mockConsoleDebug; - console.info = mockConsoleInfo; - console.warn = mockConsoleWarn; - console.error = mockConsoleError; + vi.spyOn(console, "debug").mockImplementation(mockConsoleDebug); + vi.spyOn(console, "info").mockImplementation(mockConsoleInfo); + vi.spyOn(console, "warn").mockImplementation(mockConsoleWarn); + vi.spyOn(console, "error").mockImplementation(mockConsoleError); mockConsoleDebug.mockClear(); mockConsoleInfo.mockClear(); mockConsoleWarn.mockClear(); mockConsoleError.mockClear(); logger = new ConsoleLogger(); }); afterEach(() => { - console.debug = originalConsoleDebug; - console.info = originalConsoleInfo; - console.warn = originalConsoleWarn; - console.error = originalConsoleError; + vi.restoreAllMocks();Also applies to: 22-31, 35-38
packages/core/tests/integration/e2e.spec.ts (4)
60-60: Make encoding assertion robust (utf8 vs utf-8).Avoid brittle exact match; accept both spellings.
Apply:
-expect(fs.readFile).toHaveBeenCalledWith("./test.mix.md", "utf-8"); +expect(fs.readFile).toHaveBeenCalledWith("./test.mix.md", expect.stringMatching(/^utf-?8$/));
87-89: Don’t pin the exact version in success log assertion.Future version bumps will break this test unnecessarily.
Apply:
-expect(mockLogger.info).toHaveBeenCalledWith( - "Rulesets v0.1.0 processing completed successfully!" -); +expect(mockLogger.info).toHaveBeenCalledWith( + expect.stringContaining("Rulesets v0") +);
121-133: Add negative I/O assertions on read failure.Assert no mkdir/writeFile when read fails.
Apply:
await expect(runRulesetsV0("./nonexistent.mix.md", mockLogger)).rejects.toThrow( "File not found" ); expect(mockLogger.error).toHaveBeenCalledWith( "Failed to read source file: ./nonexistent.mix.md", error ); + expect(fs.mkdir).not.toHaveBeenCalled(); + expect(fs.writeFile).not.toHaveBeenCalled();
174-174: Rename test to reflect Rulesets terminology.Avoid lingering “Mixdown” naming.
Apply:
-it("should preserve Mixdown markers in output", async () => { +it("should preserve Rulesets templating markers in output", async () => {packages/core/src/linter/index.ts (2)
71-92: Tighten rulesets validation and align example with v0.Handle arrays explicitly, ensure
versionis a string, and usev0in the example for consistency.- message: `Missing required ${getFieldName("/rulesets")}. Specify the Rulesets version (e.g., rulesets: { version: "0.1.0" }).`, + message: `Missing required ${getFieldName("/rulesets")}. Specify the Rulesets version (e.g., rulesets: { version: "v0" }).`, ... - } else if ( - typeof frontmatter.rulesets !== "object" || - frontmatter.rulesets === null || - !("version" in frontmatter.rulesets) - ) { + } else if ( + typeof frontmatter.rulesets !== "object" || + frontmatter.rulesets === null || + Array.isArray(frontmatter.rulesets) || + typeof (frontmatter.rulesets as any).version !== "string" + ) { results.push({ - message: `Invalid ${getFieldName("/rulesets")}. Expected object with version property, got ${typeof frontmatter.rulesets}.`, + message: `Invalid ${getFieldName("/rulesets")}. Expected object with string "version", got ${Array.isArray(frontmatter.rulesets) ? "array" : typeof frontmatter.rulesets}.`, line: 1, column: 1, severity: "error", });
103-113: Micro‑optimise allowed destinations membership check.Use a Set to avoid repeated linear
includesscans for large lists.- } else if (config.allowedDestinations && config.allowedDestinations.length > 0) { - // Validate allowed destinations if configured - for (const destId of Object.keys(frontmatter.destinations)) { - if (!config.allowedDestinations.includes(destId)) { + } else if (config.allowedDestinations && config.allowedDestinations.length > 0) { + // Validate allowed destinations if configured + const allowed = new Set(config.allowedDestinations); + for (const destId of Object.keys(frontmatter.destinations)) { + if (!allowed.has(destId)) { results.push({ message: `Unknown destination "${destId}". Allowed destinations: ${config.allowedDestinations.join(", ")}.`, line: 1, column: 1, severity: "warning", }); } } }packages/core/src/linter/__tests__/linter.spec.ts (4)
74-96: Rename test to reflect current validation semantics.The linter expects an object with a string
version; the title still mentions “not a string”.- it("should error when rulesets field is not a string", () => { + it("should error when rulesets is not an object with a string 'version'", () => {
124-151: Assert exactly one “unknown destination” warning for clarity.Optional: verify only a single unknown‑destination warning is emitted.
const destWarning = results.find((r) => r.message.includes("Unknown destination")); expect(destWarning).toBeDefined(); expect(destWarning!.severity).toBe("warning"); + expect(results.filter((r) => r.message.includes("Unknown destination")).length).toBe(1);
1-1: Update file header wording.Use current terminology.
-// TLDR: Unit tests for the Rulesets linter module (mixd-v0) +// TLDR: Unit tests for the Rulesets linter module (v0)
6-6: Optional: reduce fixture duplication with a tiny factory.Keeps tests tight and focused.
// helper (top-level in this file) function baseDoc(overrides: Partial<ParsedDoc["source"]> = {}): ParsedDoc { return { source: { content: "", ...overrides, }, ast: { stems: [], imports: [], variables: [], markers: [] }, } as ParsedDoc; }packages/core/src/compiler/index.ts (1)
41-44: Optionally support YAML '...' end delimiter.Frontmatter can also be terminated by '...'. Quick win if you want broader compatibility.
Apply this diff:
- if (lines[i].trim() === "---") { + const t = lines[i].trim(); + if (t === "---" || t === "...") {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (18)
.github/workflows/claude-code-review.yml(0 hunks)CHANGELOG.md(1 hunks)biome.json(1 hunks)package.json(2 hunks)packages/core/package.json(1 hunks)packages/core/src/compiler/index.ts(4 hunks)packages/core/src/destinations/__tests__/cursor-plugin.spec.ts(8 hunks)packages/core/src/destinations/__tests__/windsurf-plugin.spec.ts(9 hunks)packages/core/src/destinations/cursor-plugin.ts(3 hunks)packages/core/src/destinations/windsurf-plugin.ts(3 hunks)packages/core/src/index.ts(6 hunks)packages/core/src/interfaces/__tests__/logger.spec.ts(1 hunks)packages/core/src/interfaces/frontmatter.ts(1 hunks)packages/core/src/interfaces/logger.ts(2 hunks)packages/core/src/linter/__tests__/linter.spec.ts(9 hunks)packages/core/src/linter/index.ts(6 hunks)packages/core/tests/integration/e2e.spec.ts(5 hunks)tsconfig.json(1 hunks)
💤 Files with no reviewable changes (1)
- .github/workflows/claude-code-review.yml
🚧 Files skipped from review as they are similar to previous changes (7)
- biome.json
- packages/core/src/interfaces/frontmatter.ts
- tsconfig.json
- packages/core/src/destinations/tests/windsurf-plugin.spec.ts
- packages/core/src/destinations/tests/cursor-plugin.spec.ts
- packages/core/src/destinations/windsurf-plugin.ts
- packages/core/src/index.ts
🧰 Additional context used
🧠 Learnings (42)
📓 Common learnings
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-08-15T18:44:08.632Z
Learning: The user (galligan) successfully implemented all PR review feedback after initial discrepancies were identified, including: version marker format standardization from ruleset-v* to mixd-v* throughout PLAN-rulesets-v0.md, cross-platform build scripts using rimraf in packages/compiler/package.json, accurate package description removing CommonMark claims in root package.json, and proper commit tracking with specific hashes (f27e034 + 9ac6df9).
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-23T01:01:27.260Z
Learning: User galligan successfully implemented comprehensive review feedback for PR #93 Bun-native optimization, systematically addressing all critical and important issues including: complete Turborepo reference removal from documentation and codebase, proper build.mjs error logging with array formatting and null coalescing, bunfig.toml security improvements (disabled auto="fallback", fixed watchExclude, moved telemetry to top-level), package.json script optimization (build:all alias, CI enhancement with test:all), and lefthook ultracite command fix (removed invalid --write flag), achieving -422 lines of legacy code removal while adding +18 lines of focused improvements with zero breaking changes and enhanced security, demonstrating gold standard systematic implementation following established patterns from previous PRs.
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-08-19T17:49:13.493Z
Learning: User galligan provided comprehensive feedback on PR review issues, categorizing them by priority (high/medium/minor) and requesting systematic fixes including cross-platform build compatibility (rimraf instead of rm -rf), test framework alignment (bun:test instead of Jest), documentation-code consistency for directory exclusions, extraction of shared discovery logic to reduce duplication, and proper integration test implementation. Successfully addressed all feedback with complete code solutions.
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-09-01T22:04:41.689Z
Learning: User galligan successfully implemented comprehensive CodeRabbit feedback for PR #91 pino logger implementation, including: moving pino-pretty to optionalDependencies with graceful fallback using require.resolve() try/catch, implementing RULESETS_LOG_PRETTY environment gate for opt-in pretty formatting, adding getValidLogLevel() helper for level validation with fallback to 'info', aligning ConsoleLogger and PinoLogger level filtering with shouldLog() helper, implementing native pino error logging patterns with { err, msg } convention, improving object argument handling with direct merging, adding scoped biome.json overrides for console usage in logger files only, and making error stack test assertions resilient using substring matching. All 77 tests pass with comprehensive coverage for level filtering, environment validation, and graceful fallbacks, demonstrating production-ready dual-logger architecture following established systematic implementation patterns.
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-08-26T04:15:29.029Z
Learning: User galligan reported comprehensive fixes for PR #84 critical CodeRabbit feedback including: turbo dependency addition for CI build failure, codex provider addition to sandbox VALID_PROVIDER_TYPES, DEFAULT_CONFIG parallelCompilation property, RegExp lastIndex hazard fixes using matchAll, parallel compilation test logging enhancements, partial cache improvements storing compiled templates, .rule.md extension support for @-partial resolution, clearPartialCache fixes for hbs.partials registry, and silent LogLevel type addition. Verification confirmed extensive codex provider implementation, sophisticated CI quick fix workflow, robust partial cache system, and parallel compilation test infrastructure. Some specific claims require additional verification due to possible branch visibility issues, consistent with galligan's systematic implementation track record across multiple PRs.
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-22T21:25:13.038Z
Learning: User galligan demonstrated exceptional systematic implementation for commit b93dcf8 in PR #90, comprehensively addressing all review feedback with production-grade fixes including: README documentation alignment using proper ≥ symbol matching package.json engines exactly, package.json script semantic corrections (prepare script using 'bun run config:mdlint', format/check distinction with format writing and check verifying), shell script hardening with defaulted parameter expansions for set -u compatibility (${VAR-} pattern), Biome generator architecture improvements with centralized BIOME_SCHEMA_URL constant and Bun subprocess API with 300s timeouts, enhanced error handling with exit codes and command context, SILENCE_BIOME_WARNINGS environment gate for developer experience, and pragmatic schema version strategy maintaining 2.1.4 for base config compatibility while using 2.2.0 for generated configs, showcasing systematic precision with comprehensive verification and documentation quali...
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-09-01T22:04:41.689Z
Learning: User galligan successfully implemented comprehensive CodeRabbit feedback for PR #91 pino logger implementation with exceptional quality, including: correctly moving pino-pretty to optionalDependencies with graceful require.resolve() fallback in createTransport() method, implementing RULESETS_LOG_PRETTY environment gate for opt-in pretty formatting, adding getValidLogLevel() helper with validation against known levels and fallback to 'info', implementing shouldLog() helper for consistent level filtering across ConsoleLogger and PinoLogger, using native pino error logging patterns with { err: errorObj, msg: errorObj.message } convention, improving object argument handling with direct merging for single objects and args array for multiple arguments, adding properly scoped biome.json overrides for console usage in logger.ts and test files only, removing all biome-ignore comments from production code, and implementing comprehensive test coverage with 87 test cases covering level validation,...
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-09-01T17:50:46.629Z
Learning: User galligan successfully implemented comprehensive CodeRabbit and Copilot feedback for PR #88 Bun migration CI/CD workflow, including: eliminating code duplication by creating composite action .github/actions/setup-bun-and-deps/action.yml for reusable setup process, pinning actions to specific SHAs for security (actions/checkout08eba0b, oven-sh/setup-bun735343b, changesets/actione0145ed), fixing bun.lockb filename issue by renaming from bun.lock for proper Bun lockfile format, hardening release job with timeout-minutes: 30, explicit permissions (contents: write, pull-requests: write), and BUN_VERSION environment variable for consistency, and achieving perfect YAML formatting by removing trailing spaces and adding final newline. This demonstrates galligan's continued systematic approach to implementing feedback with production-ready GitHub Actions automation following enterprise-grade technical standards.
Learnt from: galligan
PR: outfitter-dev/blz#0
File: :0-0
Timestamp: 2025-08-27T17:01:21.600Z
Learning: User galligan successfully implemented comprehensive fixes for all 4 CodeRabbit review comments in PR #43 commit e7da15d, including: defensive error handling replacing unreachable!() with proper anyhow::bail! error message for NotModified on initial fetch, updating message from "Not modified" to "Up-to-date" in update command, adding etag and last_modified fields to FetchResult::NotModified variant for consistent metadata handling, and implementing atomic metadata writes using temp file pattern (.json.tmp) with fs::rename for data integrity, all within a massive 39K+ line initial codebase commit while maintaining production-quality standards.
<!--
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-15T16:42:04.468Z
Learning: The user (galligan) successfully implemented comprehensive fixes addressing critical configuration issues in biome.json (globals format, files configuration), bunfig.toml (exact setting), and VS Code settings (removing invalid multi-language overrides), while also resolving documentation contradictions and ensuring Ultracite preset compatibility over strict Biome 2.2.0 schema compliance.
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: packages/fieldguides/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:13:30.555Z
Learning: Applies to packages/fieldguides/**/*.md : Always lint markdown files with markdownlint-cli2 and fix issues before committing
📚 Learning: 2025-09-01T22:04:41.689Z
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-09-01T22:04:41.689Z
Learning: User galligan successfully implemented comprehensive CodeRabbit feedback for PR #91 pino logger implementation, including: moving pino-pretty to optionalDependencies with graceful fallback using require.resolve() try/catch, implementing RULESETS_LOG_PRETTY environment gate for opt-in pretty formatting, adding getValidLogLevel() helper for level validation with fallback to 'info', aligning ConsoleLogger and PinoLogger level filtering with shouldLog() helper, implementing native pino error logging patterns with { err, msg } convention, improving object argument handling with direct merging, adding scoped biome.json overrides for console usage in logger files only, and making error stack test assertions resilient using substring matching. All 77 tests pass with comprehensive coverage for level filtering, environment validation, and graceful fallbacks, demonstrating production-ready dual-logger architecture following established systematic implementation patterns.
Applied to files:
packages/core/src/interfaces/__tests__/logger.spec.tspackages/core/src/interfaces/logger.ts
📚 Learning: 2025-09-01T22:04:41.689Z
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-09-01T22:04:41.689Z
Learning: User galligan successfully implemented comprehensive CodeRabbit feedback for PR #91 pino logger implementation with exceptional quality, including: correctly moving pino-pretty to optionalDependencies with graceful require.resolve() fallback in createTransport() method, implementing RULESETS_LOG_PRETTY environment gate for opt-in pretty formatting, adding getValidLogLevel() helper with validation against known levels and fallback to 'info', implementing shouldLog() helper for consistent level filtering across ConsoleLogger and PinoLogger, using native pino error logging patterns with { err: errorObj, msg: errorObj.message } convention, improving object argument handling with direct merging for single objects and args array for multiple arguments, adding properly scoped biome.json overrides for console usage in logger.ts and test files only, removing all biome-ignore comments from production code, and implementing comprehensive test coverage with 87 test cases covering level validation,...
Applied to files:
packages/core/src/interfaces/__tests__/logger.spec.tspackages/core/src/interfaces/logger.ts
📚 Learning: 2025-08-31T14:18:47.842Z
Learnt from: galligan
PR: outfitter-dev/blz#0
File: :0-0
Timestamp: 2025-08-31T14:18:47.842Z
Learning: User galligan correctly pointed out that after modifying commits, CodeRabbit's memory may become outdated. The files were reorganized from .agents/rules/ directly to .agents/rules/conventions/rust/ subdirectory, and the primary documentation moved from CLAUDE.md to AGENTS.md files. All technical fixes (async-patterns handle.await??, compiler-loop.md jq -sr usage, agent-check.sh permissions and jq usage, storage layout documentation, MCP protocol version 2024-11-05) were properly implemented despite the file structure changes.
Applied to files:
packages/core/src/linter/__tests__/linter.spec.ts
📚 Learning: 2025-08-18T18:10:42.517Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-18T18:10:42.517Z
Learning: Applies to **/*.{test,spec}.{js,jsx,ts,tsx} : Ensure assertion functions (like expect) are placed inside an it() call
Applied to files:
packages/core/src/linter/__tests__/linter.spec.tspackages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-18T18:17:07.077Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-08-18T18:17:07.077Z
Learning: Applies to **/*.{test,spec}.{js,jsx,ts,tsx} : Ensure the assertion function (e.g., expect) is inside an it() call
Applied to files:
packages/core/src/linter/__tests__/linter.spec.tspackages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-18T18:17:07.077Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-08-18T18:17:07.077Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Ensure a message is passed when creating a built-in error
Applied to files:
packages/core/src/interfaces/logger.ts
📚 Learning: 2025-08-18T18:10:42.517Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-18T18:10:42.517Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Ensure a message is passed when creating a built-in error
Applied to files:
packages/core/src/interfaces/logger.ts
📚 Learning: 2025-08-18T18:12:55.183Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: packages/contracts/ts/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:12:55.183Z
Learning: Applies to packages/contracts/ts/**/*.ts : Keep error codes and messages consistent across the codebase.
Applied to files:
packages/core/src/interfaces/logger.ts
📚 Learning: 2025-08-18T18:12:55.183Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: packages/contracts/ts/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:12:55.183Z
Learning: Applies to packages/contracts/ts/**/*.ts : Ensure all failure modes are handled; no missing error handling paths.
Applied to files:
packages/core/src/interfaces/logger.ts
📚 Learning: 2025-08-15T18:44:08.632Z
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-08-15T18:44:08.632Z
Learning: The user (galligan) successfully implemented all PR review feedback after initial discrepancies were identified, including: version marker format standardization from ruleset-v* to mixd-v* throughout PLAN-rulesets-v0.md, cross-platform build scripts using rimraf in packages/compiler/package.json, accurate package description removing CommonMark claims in root package.json, and proper commit tracking with specific hashes (f27e034 + 9ac6df9).
Applied to files:
packages/core/tests/integration/e2e.spec.tsCHANGELOG.mdpackages/core/package.json
📚 Learning: 2025-06-28T02:42:56.229Z
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-06-28T02:42:56.229Z
Learning: The user properly justified keeping complex promisify mocks in tests because they accurately simulate Node.js util.promisify() behavior, which is essential for testing callback-to-promise conversion that production code relies on.
Applied to files:
packages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-18T18:12:55.183Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: packages/contracts/ts/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:12:55.183Z
Learning: Applies to packages/contracts/ts/**/*.test.ts : Create dedicated test files for sub-path entry points (e.g., zod-specific tests) to isolate dependency-aware logic.
Applied to files:
packages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-18T18:10:42.517Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-18T18:10:42.517Z
Learning: Applies to **/*.{test,spec}.{js,jsx,ts,tsx} : Don't use export or module.exports in test files
Applied to files:
packages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-18T18:12:19.906Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: packages/cli/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:12:19.906Z
Learning: Applies to packages/cli/src/**/*.ts : Use Node.js path.join() for all file path construction to ensure cross-platform compatibility
Applied to files:
packages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-18T18:10:42.517Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-18T18:10:42.517Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use the node: protocol for Node.js builtin modules
Applied to files:
packages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-18T18:17:07.077Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-08-18T18:17:07.077Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use the node: protocol for Node.js builtin modules
Applied to files:
packages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to **/*.test.@(ts|tsx|js|jsx) : Write tests using Bun’s test API: `import { test, expect } from "bun:test"`; do not use Jest or Vitest APIs
Applied to files:
packages/core/tests/integration/e2e.spec.tspackage.json
📚 Learning: 2025-08-18T18:10:42.517Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-18T18:10:42.517Z
Learning: Applies to **/*.{test,spec}.{js,jsx,ts,tsx} : Don't nest describe() blocks too deeply in test files
Applied to files:
packages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-18T18:17:07.077Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-08-18T18:17:07.077Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't nest describe() blocks too deeply in test files
Applied to files:
packages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-24T11:27:06.182Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-24T11:27:06.182Z
Learning: Applies to packages/**/src/__tests__/**/*.test.{ts,tsx} : Place unit tests under src/__tests__ and name them *.test.ts(x) (Vitest)
Applied to files:
packages/core/tests/integration/e2e.spec.ts
📚 Learning: 2025-08-14T03:51:26.625Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-14T03:51:26.625Z
Learning: Applies to .mixdown/src/**/*.{mix.md,md} : Author source rules in Mixdown Markdown using .mix.md (preferred) or .md extensions
Applied to files:
packages/core/tests/integration/e2e.spec.tsCHANGELOG.md
📚 Learning: 2025-08-18T18:14:06.160Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: shared/configs/changeset/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:14:06.160Z
Learning: Applies to shared/configs/changeset/**/package.json : Ensure package.json includes scripts: build, dev, and typecheck (invoked via pnpm)
Applied to files:
package.jsonpackages/core/package.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to package.json : Avoid Vite scripts/dependencies; use Bun’s HTML imports and bundler instead
Applied to files:
package.jsonpackages/core/package.json
📚 Learning: 2025-08-22T21:25:13.038Z
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-22T21:25:13.038Z
Learning: Verification revealed discrepancies between galligan's claimed fixes for PR #90 commit b93dcf8 and actual file contents: README still shows "Node.js 20+ LTS" vs package.json ">=20" (not aligned), prepare script still contains invalid "bun config:mdlint" syntax (missing run keyword), format/check script semantics remain swapped with format using lint and check using format, shell parameter expansion safety patterns ${VAR-} not found in setup.sh, and Biome generator enhancements not visible via grep patterns, suggesting either commit not pushed, wrong branch being verified, or fixes not actually implemented despite detailed documentation claiming completion.
Applied to files:
package.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to package.json : Use `bun <file>` (or `bun --hot`) for direct script execution instead of `node` or `ts-node` in scripts
Applied to files:
package.jsonpackages/core/package.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to package.json : Use `bun build <file.html|file.ts|file.css>` for build scripts instead of webpack or esbuild
Applied to files:
package.jsonpackages/core/package.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to package.json : Use `bun test` to run tests instead of `jest` or `vitest` in scripts
Applied to files:
package.jsonpackages/core/package.json
📚 Learning: 2025-08-29T20:27:03.108Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T20:27:03.108Z
Learning: Run pnpm turbo lint, typecheck, build, and test before submitting; all must pass
Applied to files:
package.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run`, `yarn run`, or `pnpm run` in package.json scripts
Applied to files:
package.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` for running shell commands instead of `execa`
Applied to files:
package.json
📚 Learning: 2025-08-14T03:50:36.782Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-14T03:50:36.782Z
Learning: Before submitting, run pnpm turbo lint && pnpm turbo test && pnpm turbo build
Applied to files:
package.jsonpackages/core/package.json
📚 Learning: 2025-08-14T03:51:26.625Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-14T03:51:26.625Z
Learning: Use mixd-* markers in code comments for version tracking (e.g., // TLDR: ... (mixd-v0))
Applied to files:
CHANGELOG.md
📚 Learning: 2025-08-14T03:51:26.625Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-14T03:51:26.625Z
Learning: Applies to .mixdown/src/**/*.mix.md : Name source rules files in kebab-case with .mix.md extension (e.g., coding-standards.mix.md)
Applied to files:
CHANGELOG.md
📚 Learning: 2025-08-14T03:51:26.625Z
Learnt from: CR
PR: outfitter-dev/rulesets#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-14T03:51:26.625Z
Learning: Applies to .mixdown/src/**/*.{mix.md,md} : Write mixes using Markdown ATX-style headers and proper fenced code blocks with language identifiers
Applied to files:
CHANGELOG.md
📚 Learning: 2025-08-23T01:01:27.260Z
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-23T01:01:27.260Z
Learning: User galligan successfully implemented comprehensive review feedback for PR #93 Bun-native optimization, systematically addressing all critical and important issues including: complete Turborepo reference removal from documentation and codebase, proper build.mjs error logging with array formatting and null coalescing, bunfig.toml security improvements (disabled auto="fallback", fixed watchExclude, moved telemetry to top-level), package.json script optimization (build:all alias, CI enhancement with test:all), and lefthook ultracite command fix (removed invalid --write flag), achieving -422 lines of legacy code removal while adding +18 lines of focused improvements with zero breaking changes and enhanced security, demonstrating gold standard systematic implementation following established patterns from previous PRs.
Applied to files:
packages/core/package.json
📚 Learning: 2025-08-19T17:49:13.493Z
Learnt from: galligan
PR: outfitter-dev/rulesets#0
File: :0-0
Timestamp: 2025-08-19T17:49:13.493Z
Learning: User galligan provided comprehensive feedback on PR review issues, categorizing them by priority (high/medium/minor) and requesting systematic fixes including cross-platform build compatibility (rimraf instead of rm -rf), test framework alignment (bun:test instead of Jest), documentation-code consistency for directory exclusions, extraction of shared discovery logic to reduce duplication, and proper integration test implementation. Successfully addressed all feedback with complete code solutions.
Applied to files:
packages/core/package.json
📚 Learning: 2025-08-22T20:51:01.048Z
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-22T20:51:01.048Z
Learning: User galligan implemented exceptional security and performance fixes for PR #90 setup script with production-grade quality: completely eliminated curl | bash vulnerability using secure temp file handling with mktemp, comprehensive verification (empty check, suspicious pattern detection like rm -rf /), and proper cleanup; added robust input validation with VALID_ENVIRONMENTS readonly array and proper error handling; implemented proper async patterns replacing Bun.sleepSync with Promise-based setTimeout and exponential backoff retry logic; added comprehensive timeout handling (5-minute/300s for builds) with structured error objects containing exitCode and signal properties; fixed type safety with explicit dev: boolean parameter in getAddCommand(); corrected CI flags adding --frozen-lockfile for Bun; cleaned up Ultracite commands removing invalid --write flags; maintained backward compatibility with 'local' as default environment; achieved 16 try-catch blocks for comprehensive error handl...
Applied to files:
packages/core/package.json
📚 Learning: 2025-08-22T21:25:13.038Z
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-22T21:25:13.038Z
Learning: User galligan demonstrated exceptional systematic implementation for commit b93dcf8 in PR #90, comprehensively addressing all review feedback with production-grade fixes including: README documentation alignment using proper ≥ symbol matching package.json engines exactly, package.json script semantic corrections (prepare script using 'bun run config:mdlint', format/check distinction with format writing and check verifying), shell script hardening with defaulted parameter expansions for set -u compatibility (${VAR-} pattern), Biome generator architecture improvements with centralized BIOME_SCHEMA_URL constant and Bun subprocess API with 300s timeouts, enhanced error handling with exit codes and command context, SILENCE_BIOME_WARNINGS environment gate for developer experience, and pragmatic schema version strategy maintaining 2.1.4 for base config compatibility while using 2.2.0 for generated configs, showcasing systematic precision with comprehensive verification and documentation quali...
Applied to files:
packages/core/package.json
📚 Learning: 2025-08-22T20:51:01.048Z
Learnt from: galligan
PR: outfitter-dev/monorepo#0
File: :0-0
Timestamp: 2025-08-22T20:51:01.048Z
Learning: User galligan successfully implemented comprehensive security and performance fixes for PR #90 setup script, including: secure Bun installation by replacing curl | bash with temp file verification and cleanup, complete type annotation coverage with explicit boolean types for function parameters, proper async/await patterns replacing Bun.sleepSync with Promise-based setTimeout, robust input validation using VALID_ENVIRONMENTS array with exit-on-invalid logic, CI flag corrections adding --frozen-lockfile for Bun, structured timeout handling for build operations (5-minute/300s limits), comprehensive error handling with structured error objects and exit codes, and command accuracy improvements removing invalid Ultracite --write flags while maintaining full backward compatibility and cross-platform support.
Applied to files:
packages/core/package.json
📚 Learning: 2025-08-18T18:14:06.160Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: shared/configs/changeset/CLAUDE.md:0-0
Timestamp: 2025-08-18T18:14:06.160Z
Learning: Applies to shared/configs/changeset/**/{tsup.config.ts,tsup.config.js,package.json} : Use tsup to build both CJS and ESM outputs, include TypeScript declarations, and generate source maps
Applied to files:
packages/core/package.json
📚 Learning: 2025-08-18T18:17:52.697Z
Learnt from: CR
PR: outfitter-dev/monorepo#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-08-18T18:17:52.697Z
Learning: Applies to **/esbuild*.@(js|ts|mjs|cjs) : Do not use esbuild; prefer `bun build`
Applied to files:
packages/core/package.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Graphite / mergeability_check
🔇 Additional comments (19)
CHANGELOG.md (1)
9-15: Changelog reads well and matches the migration scopeThe Added/Changed entries accurately capture the ESLint→Biome swap, Lefthook, sync API, and frontmatter updates. No issues.
packages/core/package.json (2)
20-20: Cross‑platform clean via rimraf is correctGood swap from rm -rf to rimraf for portability.
29-34: Runtime logging deps look right; pino‑pretty as optional is idealSolid split: pino in dependencies, pino-pretty in optionalDependencies.
package.json (2)
13-19: Script naming is clear and consistentGood separation: lint vs lint:fix; format vs format:fix; md lint with fix flag.
37-47: Keep Prettier dependency
Prettier is invoked in lefthook.yml to format Markdown/YAML files (glob "**/*.{md,yml,yaml}" →bunx prettier --write) and is required for non-TS asset formatting.Likely an incorrect or invalid review comment.
packages/core/src/interfaces/logger.ts (1)
70-80: Console errors are now surfaced — good fixStack preserved for Error instances; level gating is consistent with other methods.
packages/core/src/destinations/cursor-plugin.ts (3)
45-55: Path resolution and logging look solidSupports both outputPath and path; resolves once and logs the final path.
56-63: Robust directory creation with error loggingGood use of mkdir recursive and propagating failures.
73-77: Priority derivation matches specPrefers config.priority and falls back to metadata; mirrors schema.
packages/core/src/interfaces/__tests__/logger.spec.ts (1)
148-157: Logger tests look solid.Good isolation, interface conformance, and underlying pino instance checks.
Also applies to: 213-220, 278-292
packages/core/src/linter/index.ts (3)
59-69: Early return on missing frontmatter — LGTM.Prevents cascaded follow‑up errors and keeps messaging clean.
118-135: Helpful suggestions for missing metadata — LGTM.Clear, actionable info‑level guidance.
43-44: No lingering async calls or Promise typings detected. All downstream callers have been updated to use the synchronouslintAPI.packages/core/src/linter/__tests__/linter.spec.ts (2)
6-29: Synchronous lint usage and object‑form rulesets — LGTM.Matches the new API and schema; assertions are inside
it()per our prior guidance.Also applies to: 31-48
98-122: Destinations structure validation — LGTM.Correctly exercises the array‑vs‑object check and asserts error severity.
packages/core/src/compiler/index.ts (4)
5-6: CRLF-safe split looks good.The dedicated LINE_SPLIT_REGEX is a clean improvement.
66-69: AST pass-through — confirm parser guarantees.If ast fields can ever be undefined from older parser outputs, consider defaulting to empty arrays/objects to avoid crashes.
24-24: Compile is fully synchronous—no async usages detected
Noawait compile(...),.then(compile), orPromise<CompiledDoc>references found across the codebase.
79-79: Remove nested metadata/config suggestion—Frontmatter.destinations is flat.
The Frontmatter type inpackages/core/src/interfaces/frontmatter.tsdefines eachdestinations[destId]entry as a flat object with no nestedmetadataorconfigproperties, so spreading…destinations[destId]?.metadataor…destinations[destId]?.configwon’t compile.Likely an incorrect or invalid review comment.
| bodyContent = lines | ||
| .slice(frontmatterEnd + 1) | ||
| .join("\n") | ||
| .trim(); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Preserve original EOLs and avoid trimming body content.
.join("\n").trim() normalises line endings and strips leading/trailing whitespace, which can be content-significant. Preserve EOL style and keep body as-is.
Apply this diff:
- bodyContent = lines
- .slice(frontmatterEnd + 1)
- .join("\n")
- .trim();
+ const eol = /\r\n/.test(source.content) ? "\r\n" : "\n";
+ bodyContent = lines
+ .slice(frontmatterEnd + 1)
+ .join(eol);Also applies to: 72-72
| process.env.RULESETS_LOG_LEVEL = undefined; | ||
| }); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Unset env vars correctly to avoid flaky state.
Assigning process.env.FOO = undefined can coerce to the string "undefined". Use delete to unset.
Apply:
- process.env.RULESETS_LOG_LEVEL = undefined;
+ delete process.env.RULESETS_LOG_LEVEL;- if (originalLogLevel === undefined) {
- process.env.RULESETS_LOG_LEVEL = undefined;
- } else {
- process.env.RULESETS_LOG_LEVEL = originalLogLevel;
- }
+ if (originalLogLevel === undefined) {
+ delete process.env.RULESETS_LOG_LEVEL;
+ } else {
+ process.env.RULESETS_LOG_LEVEL = originalLogLevel;
+ }- if (originalPretty === undefined) {
- process.env.RULESETS_LOG_PRETTY = undefined;
- } else {
- process.env.RULESETS_LOG_PRETTY = originalPretty;
- }
+ if (originalPretty === undefined) {
+ delete process.env.RULESETS_LOG_PRETTY;
+ } else {
+ process.env.RULESETS_LOG_PRETTY = originalPretty;
+ }- if (originalLogLevel === undefined) {
- process.env.RULESETS_LOG_LEVEL = undefined;
- } else {
- process.env.RULESETS_LOG_LEVEL = originalLogLevel;
- }
+ if (originalLogLevel === undefined) {
+ delete process.env.RULESETS_LOG_LEVEL;
+ } else {
+ process.env.RULESETS_LOG_LEVEL = originalLogLevel;
+ }Also applies to: 241-246, 255-260, 270-275
🤖 Prompt for AI Agents
In packages/core/src/interfaces/__tests__/logger.spec.ts around lines 39-40 (and
also apply same change at 241-246, 255-260, 270-275), the test unsets
environment variables by assigning process.env.VAR = undefined which results in
the string "undefined"; change these to use delete process.env.VAR to properly
remove the variables from the environment and avoid flaky tests.
c82e7bc to
ac40457
Compare
|
Migration complete and included in PR #97 |

feat: replace ESLint with Biome and add Lefthook for git hooks
fix: resolve linting and TypeScript errors after tooling migration