mirror of
https://github.com/alirezarezvani/ClaudeForge.git
synced 2026-07-03 10:23:15 -04:00
feat(plugin): command metadata, scoped skills, local-tier support, layered hooks, Stop audit
Wave 3 - adoption hardening. Patterns adapted (in original prose, with
attribution) from MIT-licensed shanraisshan/claude-code-best-practice.
Commands (command/enhance-claude-md.md, command/sync-claude-md.md):
- Add allowed-tools / disallowedTools / argument-hint / when_to_use so the
commands auto-suggest in the slash menu and avoid permission prompts.
- disallowedTools blocks WebFetch + WebSearch on both commands.
- Drop the previous broken hooks block (array-of-{matcher, commands} shape
did not match canonical schema; was never firing).
Skills:
- skill/karpathy-guidelines/SKILL.md: paths: glob over 23 code-file
extensions, so the guardrails auto-load only when editing source, not
markdown or data.
- skill/SKILL.md: model: haiku, effort: medium, paths: scoped to CLAUDE.md
+ AGENTS.md + .claude/rules/*.md so validator/generator passes run
cheaply without changing the user-facing model.
CLAUDE.local.md personal tier:
- skill/validator.py BestPracticesValidator now accepts filename=; any
*.local.md basename waives the 150-line cap.
- hooks/validate-claude-md.py reads the exempt suffix from hooks-config.
- .gitignore covers CLAUDE.local.md, **/CLAUDE.local.md,
.claude/settings.local.json, hooks/hooks-config.local.json.
Layered hook config:
- hooks/hooks-config.json: committed defaults
(validateClaudeMd.enabled/maxLines/exemptFilenameSuffix/exitCodeOnViolation,
stopAuditLine.enabled).
- hooks/validate-claude-md.py merges hooks-config.json +
hooks-config.local.json key-by-key; honours enabled=false (silent
exit 0), configurable cap, configurable exit code.
Stop audit hook:
- hooks/audit-claude-md.py walks the project tree, prints one stderr
line: total tracked / OVER cap / near cap (>=80%). Respects
stopAuditLine.enabled from config.
- hooks/hooks.json registers Stop event with matcher "".
Guardian fail-closed contract:
- agent/claude-md-guardian.md Safety & Validation section now explicitly
requires Skill-tool invocation (no inline paraphrase of SKILL.md),
abort on missing validated output, never auto-commit, and respect
local hook config.
Verified (8/8 smoke tests):
- Both commands parse with new fields and no broken hooks block.
- karpathy paths: 23 globs, includes .py/.ts/.go/.rs.
- skill model=haiku effort=medium with CLAUDE.md path scope.
- Validator: *.local.md (300 lines) -> pass; CLAUDE.md (300) -> fail;
legacy ctor without filename -> default behavior preserved.
- hooks-config.json valid; validateClaudeMd.enabled=true, maxLines=150.
- Hook validator: default rc=2 on bloated, rc=0 when local override
disables it, rc=0 on *.local.md (exempt).
- Stop hook entry present; audit script: rc=0 with "5 CLAUDE.md tracked".
- Regression: large-fullstack root still 52 lines with chain imports.
This commit is contained in:
+26
-1
@@ -66,18 +66,24 @@ class BestPracticesValidator:
|
||||
}
|
||||
]
|
||||
|
||||
def __init__(self, content: str, project_context: Dict[str, Any] = None):
|
||||
def __init__(self, content: str, project_context: Dict[str, Any] = None, filename: str = None):
|
||||
"""
|
||||
Initialize validator with CLAUDE.md content.
|
||||
|
||||
Args:
|
||||
content: Full text content of CLAUDE.md file
|
||||
project_context: Optional project context for advanced validation
|
||||
filename: Optional path or basename. When the basename ends with
|
||||
``.local.md`` (e.g. ``CLAUDE.local.md``), the 150-line cap is
|
||||
relaxed because the file is a personal/gitignored override
|
||||
outside the chained team-shared tree.
|
||||
"""
|
||||
self.content = content
|
||||
self.lines = content.split('\n')
|
||||
self.line_count = len(self.lines)
|
||||
self.project_context = project_context or {}
|
||||
self.filename = filename or ""
|
||||
self.is_local_override = self.filename.endswith('.local.md')
|
||||
|
||||
def validate_all(self) -> Dict[str, Any]:
|
||||
"""
|
||||
@@ -112,6 +118,25 @@ class BestPracticesValidator:
|
||||
message = f"File length is appropriate ({self.line_count} lines)"
|
||||
severity = "info"
|
||||
|
||||
# CLAUDE.local.md (and any *.local.md sibling) is a personal,
|
||||
# gitignored override outside the chained team-shared tree. Skip the
|
||||
# 150-line cap — only flag underuse.
|
||||
if self.is_local_override:
|
||||
if self.line_count < self.MIN_LINES:
|
||||
status = "fail"
|
||||
message = f"Personal override is too short ({self.line_count} lines, minimum {self.MIN_LINES})"
|
||||
severity = "low"
|
||||
else:
|
||||
message = f"Personal override ({self.line_count} lines, cap waived)"
|
||||
return {
|
||||
"check": "file_length",
|
||||
"status": status,
|
||||
"message": message,
|
||||
"severity": severity,
|
||||
"actual_value": self.line_count,
|
||||
"expected_range": f"{self.MIN_LINES}+ lines (cap waived for *.local.md)",
|
||||
}
|
||||
|
||||
if self.line_count > self.MAX_RECOMMENDED_LINES:
|
||||
status = "fail"
|
||||
message = f"File exceeds maximum recommended length ({self.line_count} > {self.MAX_RECOMMENDED_LINES} lines)"
|
||||
|
||||
Reference in New Issue
Block a user