Skip to content

Day 5: Layer 1 structural validation + .claude leak fix#14

Merged
dadachi merged 1 commit intomainfrom
feat/day5-layer1-rg
Apr 22, 2026
Merged

Day 5: Layer 1 structural validation + .claude leak fix#14
dadachi merged 1 commit intomainfrom
feat/day5-layer1-rg

Conversation

@dadachi
Copy link
Copy Markdown
Contributor

@dadachi dadachi commented Apr 21, 2026

Summary

Fills runLayer1 with 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

rg isn'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

  • Recursive walk under projectDir, skipping .git, node_modules, build/, .gradle/, Pods/, DerivedData/, .build, .claude/, etc.
  • Text-file filter: TEXT_EXTS + TEXT_BASENAMES matching scripts/ruby/rename.rb's list (same surface area as the rename pass).
  • Single combined regex (alternation) over the forbidden tokens.
  • Findings: { token, file, line, text }.

Side fix — .claude/ leakage

The 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 worker SKIP_* lists included .claude. Added to all three workers. Verified the dir no longer appears in out/<slug>/*/.

This was surfaced by Layer 1 reporting ~100 false-positive token matches on .claude/settings.local.json where old substrate commit messages mentioned ItemTag.

Verified on freshly-generated clinic-queue

Stub planner rename pairs: Shop, Shopkeeper, Nativeapptemplateapi.

Platform findings pass duration
Rails 0 39ms
iOS 0 30ms
Android 0 33ms

No .claude dir in any of the three output trees.

Test plan

  • npm run ci — 7/7 green
  • Real Layer 1 run against all three generated platforms — zero findings with correct token set
  • .claude not present in out/<slug>/*/ after regen
  • Empty forbiddenTokens list short-circuits to pass: true

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>
@dadachi dadachi merged commit 7544f82 into main Apr 22, 2026
1 check passed
@dadachi dadachi deleted the feat/day5-layer1-rg branch April 22, 2026 00:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant