fix: skip framework build caches in archetype detection - #94
Conversation
The archetype file-tree walk runs under a bounded entry budget (MAX_ENTRIES),
and generated output was spending it. A `.next/` of 55 000 files consumed the
whole allowance before the walk reached `src/`, so a manifest-less React project
detected as frameworkless `lib` instead of `spa` — deterministically, on every
machine, because the walk is a sorted DFS and `.next` sorts before `src`.
Measured before: FAT {"archetypes":["lib"]} 188ms vs CONTROL (same tree minus
.next) {"archetypes":["spa"]} 1ms. After: FAT {"archetypes":["spa"]} 1ms.
A skipped dir `continue`s before the `budget -= 1` decrement, so a skip-listed
subtree costs zero entries — that ordering is the whole mechanism. Eleven build
and deploy caches join the four already skipped. The failure direction is a lost
signal, never a false one: a source file hand-authored inside one of these goes
dark, with package.json dependencies as the usual backstop.
SKIP_DIRS is now exported as a ReadonlySet so tests pin the shipped set rather
than a copy: classification neutrality for every member across four ancestor
contexts (the two `api` parent triggers and a SQL-host ancestor, so the pin
fails the day someone skips `api` or `migrations`), plus per-member skip
behavior with a paired positive control and a case-folding variant. The four
original members were only half-pinned before; all fifteen are pinned uniformly
now.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Capture the feature-pipeline stage artifacts and regress results after the archetype SKIP_DIRS fix landed. Co-authored-by: Cursor <cursoragent@cursor.com>
📝 WalkthroughWalkthroughThe archetype detector now skips fifteen cache and build directories before classification and budget accounting. Tests cover neutrality, nested paths, positive controls, and case-insensitive names. Documentation and verification artifacts describe the behavior and recorded gate results. ChangesFramework cache skip detection
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests/detect-archetype.test.ts (1)
560-595: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy liftPin the zero-budget behavior in CI.
The tests verify classification neutrality, but they do not verify that skipped directories avoid
budget -= 1. They would pass if the decrement moved before the skip, even though that would reintroduce the bounded-walk regression. Add a focused test with a mocked directory listing or a narrow test-only budget seam.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/detect-archetype.test.ts` around lines 560 - 595, Add a focused test for the skipped-directory traversal in detectArchetypesFromProject that constrains the walk budget and mocks or otherwise controls directory listings, asserting skipped entries do not consume budget and traversal still reaches the intended signal. Keep the existing classification tests unchanged and use the narrowest test-only budget seam available.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/commands/init.md`:
- Line 86: Update the documentation around the detected-tree walk to state that
directory matching is case-insensitive and that the zero-cost/zero-budget
guarantee applies only to the explicitly listed skipped directories; clarify
that unlisted caches may consume the bounded walk budget. Ensure the documented
behavior matches the implementation, marking any unsupported behavior as Coming
soon or linking to docs/roadmap.md.
---
Nitpick comments:
In `@tests/detect-archetype.test.ts`:
- Around line 560-595: Add a focused test for the skipped-directory traversal in
detectArchetypesFromProject that constrains the walk budget and mocks or
otherwise controls directory listings, asserting skipped entries do not consume
budget and traversal still reaches the intended signal. Keep the existing
classification tests unchanged and use the narrowest test-only budget seam
available.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 0fae1f48-ac3e-44a5-87ea-477002165378
📒 Files selected for processing (15)
.dev/features/detect-skip-framework-caches/GRILL.md.dev/features/detect-skip-framework-caches/PLAN.md.dev/features/detect-skip-framework-caches/REGRESSION.md.dev/features/detect-skip-framework-caches/REVIEW.md.dev/features/detect-skip-framework-caches/SHIP.md.dev/features/detect-skip-framework-caches/VERIFY.md.dev/features/detect-skip-framework-caches/regression-report.json.dev/features/detect-skip-framework-caches/verify-report.json.pharn/pharn-dev-regress/base-results.json.pharn/pharn-dev-regress/head-results.json.pharn/writes-scope.jsonCHANGELOG.mddocs/commands/init.mdsrc/lib/detect-archetype.tstests/detect-archetype.test.ts
| ### 3. Detect archetypes | ||
|
|
||
| Reads `package.json` dependency names and walks the project tree (bounded, symlink-safe, `node_modules`/`.git`/`dist`/`build` skipped) for structural signals, then reduces both to an `Archetype[]`. The detected set is shown in a "Detected archetypes" note. Only names are tested against fixed in-code allowlists — no discovered file body is read (other than `package.json`) and no untrusted value is executed, interpolated, or logged. | ||
| Reads `package.json` dependency names and walks the project tree (bounded and symlink-safe, skipping dependencies, VCS metadata, and build/deploy caches — `node_modules`, `.git`, `dist`, `build`, `out`, `coverage`, `storybook-static`, `.next`, `.nuxt`, `.svelte-kit`, `.astro`, `.turbo`, `.vercel`, `.cache`, `.parcel-cache`) for structural signals, then reduces both to an `Archetype[]`. Skipping those trees costs the walk nothing, so a large framework cache cannot exhaust its bound and hide your real source; the tradeoff is that a signal file you hand-authored inside one of those directories is not seen. The detected set is shown in a "Detected archetypes" note. Only names are tested against fixed in-code allowlists — no discovered file body is read (other than `package.json`) and no untrusted value is executed, interpolated, or logged. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Scope and complete the documented skip contract.
Line 86 should state that directory matching is case-insensitive. It should also limit the zero-budget guarantee to the listed directories, because an unlisted cache can still consume the bounded walk budget.
As per coding guidelines, docs/**/*.md must keep user-facing documentation synchronized with code; undocumented or unimplemented behavior must be marked Coming soon or linked to docs/roadmap.md.
Proposed wording
- skipping dependencies, VCS metadata, and build/deploy caches —
+ skipping dependencies, VCS metadata, and build/deploy caches (matched case-insensitively) —
- Skipping those trees costs the walk nothing, so a large framework cache cannot exhaust its bound
+ Skipping these listed directories before budget accounting costs no walk budget, so a large cache inside one of them cannot exhaust the bound📝 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.
| Reads `package.json` dependency names and walks the project tree (bounded and symlink-safe, skipping dependencies, VCS metadata, and build/deploy caches — `node_modules`, `.git`, `dist`, `build`, `out`, `coverage`, `storybook-static`, `.next`, `.nuxt`, `.svelte-kit`, `.astro`, `.turbo`, `.vercel`, `.cache`, `.parcel-cache`) for structural signals, then reduces both to an `Archetype[]`. Skipping those trees costs the walk nothing, so a large framework cache cannot exhaust its bound and hide your real source; the tradeoff is that a signal file you hand-authored inside one of those directories is not seen. The detected set is shown in a "Detected archetypes" note. Only names are tested against fixed in-code allowlists — no discovered file body is read (other than `package.json`) and no untrusted value is executed, interpolated, or logged. | |
| Reads `package.json` dependency names and walks the project tree (bounded and symlink-safe, skipping dependencies, VCS metadata, and build/deploy caches (matched case-insensitively) — `node_modules`, `.git`, `dist`, `build`, `out`, `coverage`, `storybook-static`, `.next`, `.nuxt`, `.svelte-kit`, `.astro`, `.turbo`, `.vercel`, `.cache`, `.parcel-cache`) for structural signals, then reduces both to an `Archetype[]`. Skipping these listed directories before budget accounting costs no walk budget, so a large cache inside one of them cannot exhaust the bound and hide your real source; the tradeoff is that a signal file you hand-authored inside one of those directories is not seen. The detected set is shown in a "Detected archetypes" note. Only names are tested against fixed in-code allowlists — no discovered file body is read (other than `package.json`) and no untrusted value is executed, interpolated, or logged. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/commands/init.md` at line 86, Update the documentation around the
detected-tree walk to state that directory matching is case-insensitive and that
the zero-cost/zero-budget guarantee applies only to the explicitly listed
skipped directories; clarify that unlisted caches may consume the bounded walk
budget. Ensure the documented behavior matches the implementation, marking any
unsupported behavior as Coming soon or linking to docs/roadmap.md.
Source: Coding guidelines
Summary
.next,out,coverage,.turbo,.vercel,.nuxt,.svelte-kit,.astro,.cache,.parcel-cache,storybook-static) so a large cache cannot exhaust the walk budget and hide real source (e.g..nextsorting beforesrcand detecting aslibinstead ofspa).continuebeforebudget -= 1); failure mode is a lost signal only, never a false one.SKIP_DIRSmember for skip behavior (including case-insensitive) and classification neutrality; updatesdocs/commands/init.mdandCHANGELOG.md.Test plan
npm test— especiallytests/detect-archetype.test.ts.next/andsrc/App.tsx(no framework dep inpackage.json) detects asspa, notlibnode_modules,.git,dist,build) still workMade with Cursor
Summary by CodeRabbit
New Features
Documentation
Tests