Skip to content

Commit 7ba5daf

Browse files
committed
chore(claude): add 'one path, one reference' rule to CLAUDE.md
Codifies the architectural rule that path strings are owned by exactly one path module per artifact; everything else (other scripts, READMEs, Dockerfiles, workflows) imports rather than restating. Comments that re-state the path are duplication wearing a comment costume.
1 parent bd74b72 commit 7ba5daf

1 file changed

Lines changed: 12 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,18 @@ See `docs/references/error-messages.md` for worked examples and anti-patterns.
149149
- HTTP Requests: NEVER use `fetch()` — use `httpJson`/`httpText`/`httpRequest` from `@socketsecurity/lib/http-request`
150150
- File existence: ALWAYS `existsSync` from `node:fs`. NEVER `fs.access`, `fs.stat`-for-existence, or an async `fileExists` wrapper. Import form: `import { existsSync, promises as fs } from 'node:fs'`.
151151

152+
### Paths: One Path, One Reference
153+
154+
**If a path appears in two places, that's a bug.** Every artifact (build output, cache directory, generated file, config location) lives at exactly one canonical location, and that location is defined in exactly one place — typically a `paths.mts` (or equivalent path helper) module. Everything else — other scripts, READMEs, Dockerfiles, workflows, tests — derives from that source. No hand-assembled `path.join(...)` strings outside the module that owns them.
155+
156+
- **Within a package**: every script imports its own path module. No script computes paths from raw segments.
157+
- **Across packages**: when package B consumes package A's artifact, B imports A's path module (or a typed helper exported from it) — never reconstructs the path from string segments. The classic failure: A adds a new path segment (e.g. inserts a `wasm/` directory), B's hand-built copy of the path drifts, builds break.
158+
- **Doc strings**: README "Output:" lines and `@fileoverview` comments describe the path; they don't *encode* it for tools to parse. The doc is for humans only — and even there, it must match what the path module actually produces, verified by running the function.
159+
- **Workflows / Dockerfiles**: GitHub Actions YAML and Dockerfiles can't `import` TS, so they're allowed to reference the path string directly — but they MUST add a comment pointing at the canonical path module so the next person editing knows where the source of truth lives, and any path string must match the module byte-for-byte. If you find yourself writing the same path twice in one workflow, hoist it to a step output or a job-level env var; reference that everywhere downstream.
160+
- **Comments that re-state the path**: forbidden. A comment like `// Path mirrors getBuildPaths(): build/<mode>/<arch>/out/Final/...` is duplication wearing a comment costume. The import statement is the comment.
161+
162+
When you spot duplication, the answer is never "update both" — the answer is "delete one and import the other." Fix the architecture, not the symptom.
163+
152164
### Sorting
153165

154166
Sort lists alphanumerically (literal byte order, ASCII before letters). Apply this to:

0 commit comments

Comments
 (0)