chore: harden code-standards skill from PR review feedback#9349
Conversation
Distill recurring review comments from PRs #9043, #8393, and #7347 into the code-standards skill as anti-patterns #8-20 (comment discipline, responsibility placement, no partial init, names that encode behavior, absent-vs-false booleans, domain-types-over-string-typing, not bypassing abstractions, thread-safety, algorithmic complexity, dead code, and hiding-failures). Also fix the delivery gap that let these rules go unread: CLAUDE.md's Startup section wrongly implied skills auto-load, so the code-standards skill body (only surfaced on Skill-tool invocation) never reached context. Rewrite the wording to mandate invoking it before any .cs edit, tighten the skill description to drop the "non-trivial" escape hatch, and add a PreToolUse hook that reminds once per session on .cs edits.
|
Slack notification sent to #explorer-ext-contributions for external review. |
decentraland-bot
left a comment
There was a problem hiding this comment.
PR Review: chore: harden code-standards skill from PR review feedback
STEP 2 — Root-cause check: ✅ PASS
The problem is real and well-diagnosed: the code-standards skill was effectively dead because CLAUDE.md claimed skills auto-load ("do not manually read them"), when in fact a skill's full body only enters context after explicit Skill() invocation. The fix addresses the root cause with a three-layer approach (corrected documentation + tightened skill description + deterministic hook), each targeting a distinct failure mode. This is defense-in-depth, not over-engineering.
STEP 3 — Design & integration: ✅ PASS
This PR is docs/agent-tooling only — no runtime C# code, no ECS systems, no long-lived units, no persistent state. No owner search required.
The 13 new anti-patterns (#8–20) are well-scoped:
- #8 vs existing CLAUDE.md "comments narrating caller behavior" — overlap is acknowledged with an explicit cross-reference; #8 broadens scope to authoring/testing narration and name-restating, which are distinct failure modes. Well-handled.
- #9 (leaking responsibility) vs #16 (bypassing abstraction) — related but distinct: #9 is about data-decision ownership, #16 is about using the wrong API layer. Clear separation.
- #13 (side-effects + hidden default params) — bundles two concerns under "hidden wiring" theme. Acceptable.
- #19 (dead code) — broad catch-all for cleanup patterns. Reads more like a checklist, but reasonable for this category.
No true duplicates among the 13 new entries.
STEP 4 — Member audit: N/A
No C# members added or changed.
STEP 5 — Line-level review
See inline comments below (2 × P2).
Security review
No critical or high security issues. The hook script:
- ✅ Degrades safely when
jqis unavailable (command -v jq || exit 0) - ✅ Never blocks a tool call (always exits 0)
- ✅ No command injection —
file_pathis only used in acaseglob, not interpolated into shell commands - ✅ No secrets or credentials
⚠️ session_idused unsanitized in sentinel path (see inline comment — P2)
STEP 6 — Complexity: SIMPLE
4 files, +174/−3 lines, all documentation and agent tooling. No runtime code, no ECS, no async, no assembly changes.
STEP 7 — QA: NO
No user-facing behavior affected. No runtime code changes. Nothing runs in the Unity player.
STEP 8 — Non-blocking warnings: None
Main.unity not modified.
REVIEW_RESULT: PASS ✅
COMPLEXITY: SIMPLE
COMPLEXITY_REASON: Docs and agent-tooling changes only (skill markdown, CLAUDE.md wording, bash hook, settings.json config) — no runtime C# code.
QA_REQUIRED: NO
Reviewed by Jarvis 🤖 · Requested by unknown via Slack
| name: code-standards | ||
| description: "C# naming conventions, member ordering, formatting rules, nullable reference types, memory/GC rules, test patterns, and PR standards. Use when writing, reviewing, or modifying non-trivial C# changes in this Unity project — applies to ECS systems, controllers, tests, utilities, and plugins." | ||
| description: "C# naming conventions, member ordering, formatting rules, nullable reference types, memory/GC rules, test patterns, and PR standards. Use BEFORE reading, writing, or modifying ANY .cs file in this Unity project — invoke it before the first Edit/Write on production C#, not only for large changes. Applies to ECS systems, controllers, tests, utilities, and plugins." | ||
| user-invocable: false |
There was a problem hiding this comment.
[P2] Skill description says "reading" but enforcement only covers writing/modifying. The description says "Use BEFORE reading, writing, or modifying ANY .cs file" but both the CLAUDE.md update and the PreToolUse hook only fire on Edit|Write|MultiEdit — not Read. Loading 123 lines of anti-patterns before every .cs read wastes context window for zero benefit.
Drop "reading" to align with the enforcement mechanisms.
| user-invocable: false | |
| description: "C# naming conventions, member ordering, formatting rules, nullable reference types, memory/GC rules, test patterns, and PR standards. Use BEFORE writing or modifying ANY .cs file in this Unity project — invoke it before the first Edit/Write on production C#, not only for large changes. Applies to ECS systems, controllers, tests, utilities, and plugins." |
| esac | ||
|
|
There was a problem hiding this comment.
[P2] Unsanitized session_id in sentinel file path. The session_id value from stdin JSON is interpolated directly into a file path. While session_id is set by the Claude Code runtime (not user input), defense-in-depth says to sanitize it — a crafted value with ../ could create/truncate files outside /tmp. Strip non-path-safe characters after extraction:
| esac | |
| session_id="$(printf '%s' "$input" | jq -r '.session_id // "unknown"' 2>/dev/null || echo unknown)" | |
| session_id="${session_id//[^a-zA-Z0-9_-]/}" | |
| sentinel="${TMPDIR:-/tmp}/claude-code-standards-reminder-${session_id}" |
- Drop "reading" from the code-standards skill description: neither the CLAUDE.md guidance nor the PreToolUse hook fires on Read, and loading the anti-patterns on every .cs read wastes context. Keep writing/ modifying/reviewing, which the standards actually serve. - Sanitize session_id before using it in the hook's sentinel path (strip non [A-Za-z0-9_-]) so a crafted value can't escape $TMPDIR.
|
@claude review |
|
Claude finished @cyaiox's task in 4m 4s —— View job PR Review:
|
Remove scripts/hooks/remind-code-standards.sh and revert .claude/settings.json to the Stop-lint hook only. The skill description tightening and the CLAUDE.md Startup rewrite remain and carry the intent on their own; the hook is dropped from this PR.
Pull Request Description
What does this PR change?
Turns recurring code-review feedback into durable, documented project standards, and fixes why the
code-standardsskill was going unread. Two parts:1. Capture the rules. Distills the repeated review comments from PRs #9043, #8393, and #7347 into the
code-standardsskill as anti-patterns #8–20:if-elseinstead of a domain type (REnum)IMessagePipenot rawIDataPipe).Exists) & redundant buffers in hot paths2. Fix why the skill was never read.
CLAUDE.md's Startup section implied skills auto-load ("do not manually read them"), but a skill's body is only in context once theSkilltool is invoked — so the standards never reached context. This rewrites the wording to mandate invokingSkill(code-standards)before any.csedit, and tightens the skilldescriptionto drop the "non-trivial" escape hatch.Docs/agent-tooling only — no runtime code changes.
Test Instructions
Not an in-world change; nothing to run in the explorer. Verify directly:
.claude/skills/code-standards/SKILL.md— confirm anti-patterns Game Object Creation #8–20 read clearly and each traces to real review feedback.CLAUDE.mdStartup — confirm it no longer claims skills auto-load and namesSkill(code-standards)as a pre-edit step, and the skilldescriptionno longer contains the "non-trivial" escape hatch.Prerequisites
Test Steps
Additional Testing Notes
.cschanged, so the ReSharperStoplint hook inspects nothing.Quality Checklist
Code Review Reference
Please review our Branch & PR Standards before submitting. It explains the automated review flow, QA/DEV approval requirements, and what each label does — especially useful for first-time contributors.