Day 5: Layer 1 structural validation + .claude leak fix#14
Merged
Conversation
Fills runLayer1 with a pure-Node walk (no rg dependency) that scans code files for forbidden-token substrings. Zero deps, portable to any machine with Node — rg isn't guaranteed to be a standalone binary everywhere (on this machine it was only a shell function). Layer 1 implementation: - Walks projectDir recursively, skipping .git, node_modules, build/, .gradle/, Pods/, DerivedData/, .claude, etc. - Reads text-ish files only (TEXT_EXTS + TEXT_BASENAMES mirroring rename.rb's list) - Returns findings with file / line / text / token metadata - Fast: ~30-50ms per 300-file project Side fix — substrate's .claude/ (Claude Code config, potentially user-specific prompts) was leaking into generated projects via the substrate copy. Adding .claude to SKIP_RELATIVE_PATHS (rails/ios) and SKIP_SEGMENTS (android) stops the leak. Verified on freshly-generated clinic-queue with the stub planner's rename pairs (Shop, Shopkeeper, Nativeapptemplateapi): zero Layer 1 findings across all three platforms. No .claude/ dir in generated output. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fills
runLayer1with a real implementation — structural check that scans generated code files for forbidden-token substrings (tokens that should have been renamed but weren't). Pure-Node walk, no external binary dependency.Why pure-Node over ripgrep
rgisn't guaranteed to be a regular binary on every machine the agent runs on. On this machine it turned out to be only a shell function wrapper —spawn("rg", ...)failed with ENOENT. Switched to a pure-Node traversal:fs.readdir+fs.readFile+ regex. ~30-50ms per 300-file project. More than fast enough for Layer 1, and works everywhere Node does.How it works
projectDir, skipping.git,node_modules,build/,.gradle/,Pods/,DerivedData/,.build,.claude/, etc.TEXT_EXTS+TEXT_BASENAMESmatchingscripts/ruby/rename.rb's list (same surface area as the rename pass).{ token, file, line, text }.Side fix —
.claude/leakageThe substrate's
.claude/settings.local.json(Claude Code config, potentially user-specific prompts + command allowlists) was being copied into every generated project because none of the workerSKIP_*lists included.claude. Added to all three workers. Verified the dir no longer appears inout/<slug>/*/.This was surfaced by Layer 1 reporting ~100 false-positive token matches on
.claude/settings.local.jsonwhere old substrate commit messages mentionedItemTag.Verified on freshly-generated clinic-queue
Stub planner rename pairs:
Shop,Shopkeeper,Nativeapptemplateapi.No
.claudedir in any of the three output trees.Test plan
npm run ci— 7/7 green.claudenot present inout/<slug>/*/after regenforbiddenTokenslist short-circuits topass: true