@qazuor/claude-code-config 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1248 -0
- package/dist/bin.cjs +11886 -0
- package/dist/bin.cjs.map +1 -0
- package/dist/bin.d.cts +1 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +11869 -0
- package/dist/bin.js.map +1 -0
- package/dist/index.cjs +3887 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1325 -0
- package/dist/index.d.ts +1325 -0
- package/dist/index.js +3835 -0
- package/dist/index.js.map +1 -0
- package/package.json +86 -0
- package/templates/.log/notifications.log +1775 -0
- package/templates/agents/README.md +164 -0
- package/templates/agents/_registry.json +443 -0
- package/templates/agents/design/content-writer.md +353 -0
- package/templates/agents/design/ux-ui-designer.md +382 -0
- package/templates/agents/engineering/astro-engineer.md +293 -0
- package/templates/agents/engineering/db-drizzle-engineer.md +360 -0
- package/templates/agents/engineering/express-engineer.md +316 -0
- package/templates/agents/engineering/fastify-engineer.md +399 -0
- package/templates/agents/engineering/hono-engineer.md +263 -0
- package/templates/agents/engineering/mongoose-engineer.md +473 -0
- package/templates/agents/engineering/nestjs-engineer.md +429 -0
- package/templates/agents/engineering/nextjs-engineer.md +451 -0
- package/templates/agents/engineering/node-typescript-engineer.md +347 -0
- package/templates/agents/engineering/prisma-engineer.md +432 -0
- package/templates/agents/engineering/react-senior-dev.md +394 -0
- package/templates/agents/engineering/tanstack-start-engineer.md +447 -0
- package/templates/agents/engineering/tech-lead.md +269 -0
- package/templates/agents/product/product-functional.md +329 -0
- package/templates/agents/product/product-technical.md +578 -0
- package/templates/agents/quality/debugger.md +514 -0
- package/templates/agents/quality/qa-engineer.md +390 -0
- package/templates/agents/specialized/enrichment-agent.md +277 -0
- package/templates/agents/specialized/i18n-specialist.md +322 -0
- package/templates/agents/specialized/seo-ai-specialist.md +387 -0
- package/templates/agents/specialized/tech-writer.md +300 -0
- package/templates/code-style/.editorconfig +27 -0
- package/templates/code-style/.prettierignore +25 -0
- package/templates/code-style/.prettierrc +12 -0
- package/templates/code-style/biome.json +78 -0
- package/templates/code-style/commitlint.config.js +44 -0
- package/templates/commands/README.md +175 -0
- package/templates/commands/_registry.json +420 -0
- package/templates/commands/add-new-entity.md +211 -0
- package/templates/commands/audit/accessibility-audit.md +360 -0
- package/templates/commands/audit/performance-audit.md +290 -0
- package/templates/commands/audit/security-audit.md +231 -0
- package/templates/commands/code-check.md +127 -0
- package/templates/commands/five-why.md +225 -0
- package/templates/commands/formatting/format-markdown.md +197 -0
- package/templates/commands/git/commit.md +247 -0
- package/templates/commands/meta/create-agent.md +257 -0
- package/templates/commands/meta/create-command.md +312 -0
- package/templates/commands/meta/create-skill.md +321 -0
- package/templates/commands/meta/help.md +318 -0
- package/templates/commands/planning/check-completed-tasks.md +224 -0
- package/templates/commands/planning/cleanup-issues.md +248 -0
- package/templates/commands/planning/planning-cleanup.md +251 -0
- package/templates/commands/planning/sync-planning-github.md +133 -0
- package/templates/commands/planning/sync-todos-github.md +203 -0
- package/templates/commands/quality-check.md +211 -0
- package/templates/commands/run-tests.md +159 -0
- package/templates/commands/start-feature-plan.md +232 -0
- package/templates/commands/start-refactor-plan.md +244 -0
- package/templates/commands/sync-planning.md +176 -0
- package/templates/commands/update-docs.md +242 -0
- package/templates/docs/CHECKPOINT-SYSTEM.md +504 -0
- package/templates/docs/INDEX.md +677 -0
- package/templates/docs/RECOMMENDED-HOOKS.md +415 -0
- package/templates/docs/_registry.json +329 -0
- package/templates/docs/diagrams/README.md +220 -0
- package/templates/docs/diagrams/agent-hierarchy.mmd +55 -0
- package/templates/docs/diagrams/documentation-map.mmd +61 -0
- package/templates/docs/diagrams/tools-relationship.mmd +55 -0
- package/templates/docs/diagrams/workflow-decision-tree.mmd +38 -0
- package/templates/docs/doc-sync.md +533 -0
- package/templates/docs/examples/end-to-end-workflow.md +1505 -0
- package/templates/docs/glossary.md +495 -0
- package/templates/docs/guides/mockup-prompt-engineering.md +644 -0
- package/templates/docs/guides/mockup-setup.md +737 -0
- package/templates/docs/learnings/README.md +250 -0
- package/templates/docs/learnings/common-architectural-patterns.md +123 -0
- package/templates/docs/learnings/common-mistakes-to-avoid.md +149 -0
- package/templates/docs/learnings/markdown-formatting-standards.md +104 -0
- package/templates/docs/learnings/monorepo-command-execution.md +64 -0
- package/templates/docs/learnings/optimization-tips.md +146 -0
- package/templates/docs/learnings/planning-linear-sync-workflow.md +70 -0
- package/templates/docs/learnings/shell-compatibility-fish.md +46 -0
- package/templates/docs/learnings/test-organization-structure.md +68 -0
- package/templates/docs/mcp-installation.md +613 -0
- package/templates/docs/mcp-servers.md +989 -0
- package/templates/docs/notification-installation.md +570 -0
- package/templates/docs/quick-start.md +354 -0
- package/templates/docs/standards/architecture-patterns.md +1064 -0
- package/templates/docs/standards/atomic-commits.md +513 -0
- package/templates/docs/standards/code-standards.md +993 -0
- package/templates/docs/standards/design-standards.md +656 -0
- package/templates/docs/standards/documentation-standards.md +1160 -0
- package/templates/docs/standards/testing-standards.md +969 -0
- package/templates/docs/system-maintenance.md +604 -0
- package/templates/docs/templates/PDR-template.md +561 -0
- package/templates/docs/templates/TODOs-template.md +534 -0
- package/templates/docs/templates/tech-analysis-template.md +800 -0
- package/templates/docs/workflows/README.md +519 -0
- package/templates/docs/workflows/atomic-task-protocol.md +955 -0
- package/templates/docs/workflows/decision-tree.md +482 -0
- package/templates/docs/workflows/edge-cases.md +856 -0
- package/templates/docs/workflows/phase-1-planning.md +957 -0
- package/templates/docs/workflows/phase-2-implementation.md +896 -0
- package/templates/docs/workflows/phase-3-validation.md +792 -0
- package/templates/docs/workflows/phase-4-finalization.md +927 -0
- package/templates/docs/workflows/quick-fix-protocol.md +505 -0
- package/templates/docs/workflows/task-atomization.md +537 -0
- package/templates/docs/workflows/task-completion-protocol.md +448 -0
- package/templates/hooks/on-notification.sh +28 -0
- package/templates/schemas/checkpoint.schema.json +97 -0
- package/templates/schemas/code-registry.schema.json +84 -0
- package/templates/schemas/pdr.schema.json +314 -0
- package/templates/schemas/problems.schema.json +55 -0
- package/templates/schemas/tech-analysis.schema.json +404 -0
- package/templates/schemas/telemetry.schema.json +298 -0
- package/templates/schemas/todos.schema.json +234 -0
- package/templates/schemas/workflows.schema.json +69 -0
- package/templates/scripts/add-changelogs.sh +105 -0
- package/templates/scripts/generate-code-registry.ts +270 -0
- package/templates/scripts/health-check.sh +343 -0
- package/templates/scripts/sync-registry.sh +40 -0
- package/templates/scripts/telemetry-report.ts +36 -0
- package/templates/scripts/validate-docs.sh +224 -0
- package/templates/scripts/validate-registry.sh +225 -0
- package/templates/scripts/validate-schemas.ts +283 -0
- package/templates/scripts/validate-structure.sh +165 -0
- package/templates/scripts/worktree-cleanup.sh +81 -0
- package/templates/scripts/worktree-create.sh +63 -0
- package/templates/sessions/planning/.gitkeep +0 -0
- package/templates/sessions/planning/archived/.gitkeep +0 -0
- package/templates/settings.json +202 -0
- package/templates/settings.local.json +138 -0
- package/templates/skills/README.md +197 -0
- package/templates/skills/_registry.json +473 -0
- package/templates/skills/audit/accessibility-audit.md +309 -0
- package/templates/skills/audit/performance-audit.md +257 -0
- package/templates/skills/audit/security-audit.md +217 -0
- package/templates/skills/auth/nextauth-patterns.md +308 -0
- package/templates/skills/brand-guidelines.md +240 -0
- package/templates/skills/documentation/markdown-formatter.md +302 -0
- package/templates/skills/git/git-commit-helper.md +321 -0
- package/templates/skills/i18n/i18n-patterns.md +251 -0
- package/templates/skills/patterns/error-handling-patterns.md +242 -0
- package/templates/skills/patterns/tdd-methodology.md +342 -0
- package/templates/skills/qa/qa-criteria-validator.md +383 -0
- package/templates/skills/qa/web-app-testing.md +398 -0
- package/templates/skills/react/react-hook-form-patterns.md +359 -0
- package/templates/skills/state/redux-toolkit-patterns.md +272 -0
- package/templates/skills/state/tanstack-query-patterns.md +299 -0
- package/templates/skills/state/zustand-patterns.md +301 -0
- package/templates/skills/tech/mermaid-diagram-specialist.md +195 -0
- package/templates/skills/tech/shadcn-specialist.md +252 -0
- package/templates/skills/tech/vercel-specialist.md +297 -0
- package/templates/skills/testing/api-app-testing.md +254 -0
- package/templates/skills/testing/performance-testing.md +275 -0
- package/templates/skills/testing/security-testing.md +348 -0
- package/templates/skills/utils/add-memory.md +295 -0
- package/templates/skills/utils/json-data-auditor.md +283 -0
- package/templates/skills/utils/pdf-creator-editor.md +342 -0
- package/templates/tools/format-markdown.sh +185 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Code Registry Validation Script
|
|
4
|
+
#
|
|
5
|
+
# Validates .code-registry.json against its JSON schema and checks data integrity
|
|
6
|
+
#
|
|
7
|
+
# Exit codes:
|
|
8
|
+
# 0 - Validation passed
|
|
9
|
+
# 1 - Validation failed
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
# Colors
|
|
15
|
+
RED='\033[0;31m'
|
|
16
|
+
YELLOW='\033[1;33m'
|
|
17
|
+
GREEN='\033[0;32m'
|
|
18
|
+
BLUE='\033[0;34m'
|
|
19
|
+
NC='\033[0m' # No Color
|
|
20
|
+
|
|
21
|
+
REGISTRY_FILE=".claude/sessions/planning/.code-registry.json"
|
|
22
|
+
SCHEMA_FILE=".claude/schemas/code-registry.schema.json"
|
|
23
|
+
|
|
24
|
+
error() {
|
|
25
|
+
echo -e "${RED}✗ $1${NC}"
|
|
26
|
+
exit 1
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
warning() {
|
|
30
|
+
echo -e "${YELLOW}⚠ $1${NC}"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
success() {
|
|
34
|
+
echo -e "${GREEN}✓ $1${NC}"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
info() {
|
|
38
|
+
echo -e "${BLUE}ℹ $1${NC}"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
echo -e "${BLUE}🔍 Validating code registry...${NC}"
|
|
42
|
+
echo ""
|
|
43
|
+
|
|
44
|
+
# ============================================================================
|
|
45
|
+
# 1. Check file existence
|
|
46
|
+
# ============================================================================
|
|
47
|
+
|
|
48
|
+
if [ ! -f "$REGISTRY_FILE" ]; then
|
|
49
|
+
error "Code registry not found: $REGISTRY_FILE"
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
success "Registry file exists"
|
|
53
|
+
|
|
54
|
+
if [ ! -f "$SCHEMA_FILE" ]; then
|
|
55
|
+
error "Schema file not found: $SCHEMA_FILE"
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
success "Schema file exists"
|
|
59
|
+
|
|
60
|
+
# ============================================================================
|
|
61
|
+
# 2. Validate JSON syntax
|
|
62
|
+
# ============================================================================
|
|
63
|
+
|
|
64
|
+
if ! jq empty "$REGISTRY_FILE" 2>/dev/null; then
|
|
65
|
+
error "Registry is not valid JSON"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
success "Registry is valid JSON"
|
|
69
|
+
|
|
70
|
+
# ============================================================================
|
|
71
|
+
# 3. Validate against JSON Schema (using Node + AJV)
|
|
72
|
+
# ============================================================================
|
|
73
|
+
|
|
74
|
+
echo ""
|
|
75
|
+
echo "📋 Validating against schema..."
|
|
76
|
+
|
|
77
|
+
# Create temporary validation script
|
|
78
|
+
TEMP_SCRIPT=$(mktemp)
|
|
79
|
+
cat > "$TEMP_SCRIPT" << 'EOF'
|
|
80
|
+
const Ajv = require('ajv');
|
|
81
|
+
const addFormats = require('ajv-formats');
|
|
82
|
+
const fs = require('fs');
|
|
83
|
+
|
|
84
|
+
const ajv = new Ajv({ allErrors: true, verbose: true });
|
|
85
|
+
addFormats(ajv);
|
|
86
|
+
|
|
87
|
+
const schemaPath = process.argv[2];
|
|
88
|
+
const dataPath = process.argv[3];
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8'));
|
|
92
|
+
const data = JSON.parse(fs.readFileSync(dataPath, 'utf-8'));
|
|
93
|
+
|
|
94
|
+
const validate = ajv.compile(schema);
|
|
95
|
+
const valid = validate(data);
|
|
96
|
+
|
|
97
|
+
if (!valid) {
|
|
98
|
+
console.error('Schema validation failed:');
|
|
99
|
+
console.error(JSON.stringify(validate.errors, null, 2));
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.log('✓ Schema validation passed');
|
|
104
|
+
process.exit(0);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.error('Validation error:', error.message);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
EOF
|
|
110
|
+
|
|
111
|
+
if node "$TEMP_SCRIPT" "$SCHEMA_FILE" "$REGISTRY_FILE" 2>/dev/null; then
|
|
112
|
+
success "Schema validation passed"
|
|
113
|
+
else
|
|
114
|
+
rm -f "$TEMP_SCRIPT"
|
|
115
|
+
error "Schema validation failed"
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
rm -f "$TEMP_SCRIPT"
|
|
119
|
+
|
|
120
|
+
# ============================================================================
|
|
121
|
+
# 4. Extract and display statistics
|
|
122
|
+
# ============================================================================
|
|
123
|
+
|
|
124
|
+
echo ""
|
|
125
|
+
echo "📊 Registry Statistics"
|
|
126
|
+
echo "======================"
|
|
127
|
+
|
|
128
|
+
VERSION=$(jq -r '.version' "$REGISTRY_FILE")
|
|
129
|
+
GENERATED_AT=$(jq -r '.generatedAt' "$REGISTRY_FILE")
|
|
130
|
+
LAST_PLANNING=$(jq -r '.lastPlanningNumber' "$REGISTRY_FILE")
|
|
131
|
+
TOTAL_SESSIONS=$(jq '.registry | length' "$REGISTRY_FILE")
|
|
132
|
+
|
|
133
|
+
echo " Version: $VERSION"
|
|
134
|
+
echo " Generated: $GENERATED_AT"
|
|
135
|
+
echo " Last planning number: $LAST_PLANNING"
|
|
136
|
+
echo " Total sessions: $TOTAL_SESSIONS"
|
|
137
|
+
|
|
138
|
+
# Count by type
|
|
139
|
+
FEATURE_COUNT=$(jq '[.registry[] | select(.type == "feature")] | length' "$REGISTRY_FILE")
|
|
140
|
+
REFACTOR_COUNT=$(jq '[.registry[] | select(.type == "refactor")] | length' "$REGISTRY_FILE")
|
|
141
|
+
BUGFIX_COUNT=$(jq '[.registry[] | select(.type == "bugfix")] | length' "$REGISTRY_FILE")
|
|
142
|
+
|
|
143
|
+
echo ""
|
|
144
|
+
echo " By Type:"
|
|
145
|
+
echo " ├─ Features: $FEATURE_COUNT"
|
|
146
|
+
echo " ├─ Refactors: $REFACTOR_COUNT"
|
|
147
|
+
echo " └─ Bugfixes: $BUGFIX_COUNT"
|
|
148
|
+
|
|
149
|
+
# Count by status
|
|
150
|
+
ACTIVE_COUNT=$(jq '[.registry[] | select(.status == "active")] | length' "$REGISTRY_FILE")
|
|
151
|
+
COMPLETED_COUNT=$(jq '[.registry[] | select(.status == "completed")] | length' "$REGISTRY_FILE")
|
|
152
|
+
ARCHIVED_COUNT=$(jq '[.registry[] | select(.status == "archived")] | length' "$REGISTRY_FILE")
|
|
153
|
+
CANCELLED_COUNT=$(jq '[.registry[] | select(.status == "cancelled")] | length' "$REGISTRY_FILE")
|
|
154
|
+
|
|
155
|
+
echo ""
|
|
156
|
+
echo " By Status:"
|
|
157
|
+
echo " ├─ Active: $ACTIVE_COUNT"
|
|
158
|
+
echo " ├─ Completed: $COMPLETED_COUNT"
|
|
159
|
+
echo " ├─ Archived: $ARCHIVED_COUNT"
|
|
160
|
+
echo " └─ Cancelled: $CANCELLED_COUNT"
|
|
161
|
+
|
|
162
|
+
# Total tasks
|
|
163
|
+
TOTAL_TASKS=$(jq '[.registry[].tasks | length] | add // 0' "$REGISTRY_FILE")
|
|
164
|
+
echo ""
|
|
165
|
+
echo " Total tasks: $TOTAL_TASKS"
|
|
166
|
+
|
|
167
|
+
# ============================================================================
|
|
168
|
+
# 5. Validate session paths exist
|
|
169
|
+
# ============================================================================
|
|
170
|
+
|
|
171
|
+
echo ""
|
|
172
|
+
echo "🔍 Validating session paths..."
|
|
173
|
+
|
|
174
|
+
MISSING_PATHS=0
|
|
175
|
+
jq -r '.registry[].sessionPath' "$REGISTRY_FILE" | while read -r path; do
|
|
176
|
+
SESSION_PATH=".claude/sessions/planning/$path"
|
|
177
|
+
if [ ! -d "$SESSION_PATH" ]; then
|
|
178
|
+
warning "Session path not found: $path"
|
|
179
|
+
((MISSING_PATHS++))
|
|
180
|
+
fi
|
|
181
|
+
done
|
|
182
|
+
|
|
183
|
+
if [ "$MISSING_PATHS" -eq 0 ]; then
|
|
184
|
+
success "All session paths exist"
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
# ============================================================================
|
|
188
|
+
# 6. Check staleness
|
|
189
|
+
# ============================================================================
|
|
190
|
+
|
|
191
|
+
echo ""
|
|
192
|
+
echo "⏰ Checking freshness..."
|
|
193
|
+
|
|
194
|
+
CURRENT_TIME=$(date +%s)
|
|
195
|
+
GENERATED_TIME=$(date -d "$GENERATED_AT" +%s 2>/dev/null || echo "0")
|
|
196
|
+
|
|
197
|
+
if [ "$GENERATED_TIME" -gt 0 ]; then
|
|
198
|
+
TIME_DIFF=$((CURRENT_TIME - GENERATED_TIME))
|
|
199
|
+
DAYS_OLD=$((TIME_DIFF / 86400))
|
|
200
|
+
|
|
201
|
+
if [ $DAYS_OLD -gt 7 ]; then
|
|
202
|
+
warning "Registry is $DAYS_OLD days old - consider regenerating"
|
|
203
|
+
info "Run: pnpm claude:sync:registry"
|
|
204
|
+
else
|
|
205
|
+
success "Registry is fresh ($DAYS_OLD days old)"
|
|
206
|
+
fi
|
|
207
|
+
else
|
|
208
|
+
warning "Could not determine registry age"
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
# ============================================================================
|
|
212
|
+
# Summary
|
|
213
|
+
# ============================================================================
|
|
214
|
+
|
|
215
|
+
echo ""
|
|
216
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
217
|
+
echo ""
|
|
218
|
+
success "Code registry validation complete"
|
|
219
|
+
echo ""
|
|
220
|
+
echo " Sessions: $TOTAL_SESSIONS ($ACTIVE_COUNT active)"
|
|
221
|
+
echo " Tasks: $TOTAL_TASKS"
|
|
222
|
+
echo " Last planning: $LAST_PLANNING"
|
|
223
|
+
echo ""
|
|
224
|
+
|
|
225
|
+
exit 0
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Schema Validation Script
|
|
4
|
+
*
|
|
5
|
+
* Validates JSON files and markdown frontmatter against JSON schemas.
|
|
6
|
+
* Uses ajv for schema validation.
|
|
7
|
+
*
|
|
8
|
+
* Exit codes:
|
|
9
|
+
* 0 - All validations passed
|
|
10
|
+
* 1 - Validation failed
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { readFileSync, readdirSync, statSync } from 'node:fs';
|
|
14
|
+
import { join, resolve, dirname, basename } from 'node:path';
|
|
15
|
+
import Ajv from 'ajv';
|
|
16
|
+
import addFormats from 'ajv-formats';
|
|
17
|
+
|
|
18
|
+
// Initialize ajv with formats (for date-time, uri, etc.)
|
|
19
|
+
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
20
|
+
addFormats(ajv);
|
|
21
|
+
|
|
22
|
+
// Counters
|
|
23
|
+
let totalFiles = 0;
|
|
24
|
+
let validFiles = 0;
|
|
25
|
+
let invalidFiles = 0;
|
|
26
|
+
const errors: Array<{ file: string; path?: string; error: string }> = [];
|
|
27
|
+
|
|
28
|
+
// Directories
|
|
29
|
+
const SCHEMAS_DIR = resolve(process.cwd(), '.claude/schemas');
|
|
30
|
+
const PLANNING_DIR = resolve(process.cwd(), '.claude/sessions/planning');
|
|
31
|
+
|
|
32
|
+
// Schema mappings: filename pattern -> schema file
|
|
33
|
+
const SCHEMA_MAPPINGS: Record<string, string> = {
|
|
34
|
+
'PDR.md': 'pdr.schema.json',
|
|
35
|
+
'tech-analysis.md': 'tech-analysis.schema.json',
|
|
36
|
+
'TODOs.md': 'todos.schema.json',
|
|
37
|
+
'problems.md': 'problems.schema.json',
|
|
38
|
+
'.checkpoint.json': 'checkpoint.schema.json',
|
|
39
|
+
'.code-registry.json': 'code-registry.schema.json'
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Schema cache
|
|
43
|
+
const schemaCache = new Map<string, ReturnType<typeof ajv.compile>>();
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Load and compile a JSON schema (with caching)
|
|
47
|
+
*/
|
|
48
|
+
function loadSchema(schemaFile: string) {
|
|
49
|
+
// Return cached schema if exists
|
|
50
|
+
if (schemaCache.has(schemaFile)) {
|
|
51
|
+
return schemaCache.get(schemaFile)!;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const schemaPath = join(SCHEMAS_DIR, schemaFile);
|
|
55
|
+
const schemaData = readFileSync(schemaPath, 'utf-8');
|
|
56
|
+
const schema = JSON.parse(schemaData);
|
|
57
|
+
const compiled = ajv.compile(schema);
|
|
58
|
+
|
|
59
|
+
// Cache the compiled schema
|
|
60
|
+
schemaCache.set(schemaFile, compiled);
|
|
61
|
+
|
|
62
|
+
return compiled;
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error(`❌ Error loading schema ${schemaFile}:`, error);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Extract frontmatter from markdown file
|
|
71
|
+
*/
|
|
72
|
+
function extractFrontmatter(content: string): Record<string, string> | null {
|
|
73
|
+
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---/;
|
|
74
|
+
const match = content.match(frontmatterRegex);
|
|
75
|
+
|
|
76
|
+
if (!match) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
// Simple YAML-like parsing (supports basic key: value pairs)
|
|
82
|
+
const yamlContent = match[1];
|
|
83
|
+
const data: Record<string, string> = {};
|
|
84
|
+
|
|
85
|
+
yamlContent.split('\n').forEach((line) => {
|
|
86
|
+
const colonIndex = line.indexOf(':');
|
|
87
|
+
if (colonIndex > 0) {
|
|
88
|
+
const key = line.substring(0, colonIndex).trim();
|
|
89
|
+
const value = line.substring(colonIndex + 1).trim();
|
|
90
|
+
|
|
91
|
+
// Remove quotes if present
|
|
92
|
+
data[key] = value.replace(/^["']|["']$/g, '');
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
return data;
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error(' Error parsing frontmatter:', error);
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Validate a JSON file against a schema
|
|
105
|
+
*/
|
|
106
|
+
function validateJsonFile(filePath: string, schemaFile: string): boolean {
|
|
107
|
+
totalFiles++;
|
|
108
|
+
|
|
109
|
+
const validate = loadSchema(schemaFile);
|
|
110
|
+
if (!validate) {
|
|
111
|
+
invalidFiles++;
|
|
112
|
+
errors.push({ file: filePath, error: `Schema ${schemaFile} not found or invalid` });
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const fileContent = readFileSync(filePath, 'utf-8');
|
|
118
|
+
const data = JSON.parse(fileContent);
|
|
119
|
+
|
|
120
|
+
const valid = validate(data);
|
|
121
|
+
|
|
122
|
+
if (valid) {
|
|
123
|
+
validFiles++;
|
|
124
|
+
console.log(` ✓ ${basename(filePath)}`);
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
invalidFiles++;
|
|
129
|
+
console.log(` ✗ ${basename(filePath)}`);
|
|
130
|
+
|
|
131
|
+
if (validate.errors) {
|
|
132
|
+
validate.errors.forEach((error) => {
|
|
133
|
+
console.log(` → ${error.instancePath || '/'}: ${error.message}`);
|
|
134
|
+
errors.push({
|
|
135
|
+
file: filePath,
|
|
136
|
+
path: error.instancePath,
|
|
137
|
+
error: error.message || 'Unknown error'
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return false;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
invalidFiles++;
|
|
145
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
146
|
+
console.log(` ✗ ${basename(filePath)} - ${errorMessage}`);
|
|
147
|
+
errors.push({ file: filePath, error: errorMessage });
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Validate a markdown file's frontmatter
|
|
154
|
+
*/
|
|
155
|
+
function validateMarkdownFile(filePath: string, schemaFile: string): boolean {
|
|
156
|
+
totalFiles++;
|
|
157
|
+
|
|
158
|
+
const validate = loadSchema(schemaFile);
|
|
159
|
+
if (!validate) {
|
|
160
|
+
invalidFiles++;
|
|
161
|
+
errors.push({ file: filePath, error: `Schema ${schemaFile} not found or invalid` });
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
const fileContent = readFileSync(filePath, 'utf-8');
|
|
167
|
+
const frontmatter = extractFrontmatter(fileContent);
|
|
168
|
+
|
|
169
|
+
if (!frontmatter) {
|
|
170
|
+
console.log(` ⚠ ${basename(filePath)} - No frontmatter found (skipping)`);
|
|
171
|
+
totalFiles--; // Don't count files without frontmatter
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const valid = validate(frontmatter);
|
|
176
|
+
|
|
177
|
+
if (valid) {
|
|
178
|
+
validFiles++;
|
|
179
|
+
console.log(` ✓ ${basename(filePath)}`);
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
invalidFiles++;
|
|
184
|
+
console.log(` ✗ ${basename(filePath)}`);
|
|
185
|
+
|
|
186
|
+
if (validate.errors) {
|
|
187
|
+
validate.errors.forEach((error) => {
|
|
188
|
+
console.log(` → ${error.instancePath || '/'}: ${error.message}`);
|
|
189
|
+
errors.push({
|
|
190
|
+
file: filePath,
|
|
191
|
+
path: error.instancePath,
|
|
192
|
+
error: error.message || 'Unknown error'
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return false;
|
|
198
|
+
} catch (error) {
|
|
199
|
+
invalidFiles++;
|
|
200
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
201
|
+
console.log(` ✗ ${basename(filePath)} - ${errorMessage}`);
|
|
202
|
+
errors.push({ file: filePath, error: errorMessage });
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Find all files matching a pattern in a directory
|
|
209
|
+
*/
|
|
210
|
+
function findFiles(baseDir: string, pattern: string): string[] {
|
|
211
|
+
const results: string[] = [];
|
|
212
|
+
|
|
213
|
+
function walk(dir: string) {
|
|
214
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
215
|
+
|
|
216
|
+
for (const entry of entries) {
|
|
217
|
+
const fullPath = join(dir, entry.name);
|
|
218
|
+
|
|
219
|
+
if (entry.isDirectory()) {
|
|
220
|
+
// Skip node_modules and hidden directories
|
|
221
|
+
if (!entry.name.startsWith('.') && entry.name !== 'node_modules') {
|
|
222
|
+
walk(fullPath);
|
|
223
|
+
}
|
|
224
|
+
} else if (entry.isFile()) {
|
|
225
|
+
if (entry.name === pattern || entry.name.endsWith(pattern)) {
|
|
226
|
+
results.push(fullPath);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
walk(baseDir);
|
|
233
|
+
return results;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Main validation logic
|
|
238
|
+
*/
|
|
239
|
+
function main() {
|
|
240
|
+
console.log('🔍 Validating schemas...\n');
|
|
241
|
+
|
|
242
|
+
// Validate each file type
|
|
243
|
+
for (const [filePattern, schemaFile] of Object.entries(SCHEMA_MAPPINGS)) {
|
|
244
|
+
console.log(`📄 Validating ${filePattern} files against ${schemaFile}...`);
|
|
245
|
+
|
|
246
|
+
const files = findFiles(PLANNING_DIR, filePattern);
|
|
247
|
+
|
|
248
|
+
if (files.length === 0) {
|
|
249
|
+
console.log(' (No files found)\n');
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
files.forEach((file) => {
|
|
254
|
+
if (file.endsWith('.json')) {
|
|
255
|
+
validateJsonFile(file, schemaFile);
|
|
256
|
+
} else if (file.endsWith('.md')) {
|
|
257
|
+
validateMarkdownFile(file, schemaFile);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
console.log('');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Summary
|
|
265
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
266
|
+
console.log('');
|
|
267
|
+
|
|
268
|
+
if (invalidFiles === 0) {
|
|
269
|
+
console.log('✅ All validations passed!');
|
|
270
|
+
console.log(` Total files: ${totalFiles}`);
|
|
271
|
+
console.log(` Valid: ${validFiles}`);
|
|
272
|
+
process.exit(0);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
console.log('❌ Validation failed!');
|
|
276
|
+
console.log(` Total files: ${totalFiles}`);
|
|
277
|
+
console.log(` Valid: ${validFiles}`);
|
|
278
|
+
console.log(` Invalid: ${invalidFiles}`);
|
|
279
|
+
console.log(` Errors: ${errors.length}`);
|
|
280
|
+
process.exit(1);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
main();
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# validate-structure.sh
|
|
4
|
+
# Validates the complete .claude directory structure
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
echo "🔍 Validating .claude directory structure..."
|
|
9
|
+
echo ""
|
|
10
|
+
|
|
11
|
+
ERRORS=0
|
|
12
|
+
WARNINGS=0
|
|
13
|
+
|
|
14
|
+
# Colors
|
|
15
|
+
RED='\033[0;31m'
|
|
16
|
+
YELLOW='\033[1;33m'
|
|
17
|
+
GREEN='\033[0;32m'
|
|
18
|
+
NC='\033[0m' # No Color
|
|
19
|
+
|
|
20
|
+
error() {
|
|
21
|
+
echo -e "${RED}✗ $1${NC}"
|
|
22
|
+
ERRORS=$((ERRORS + 1))
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
warning() {
|
|
26
|
+
echo -e "${YELLOW}⚠ $1${NC}"
|
|
27
|
+
WARNINGS=$((WARNINGS + 1))
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
success() {
|
|
31
|
+
echo -e "${GREEN}✓ $1${NC}"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# Check required directories
|
|
35
|
+
echo "📁 Checking directory structure..."
|
|
36
|
+
|
|
37
|
+
REQUIRED_DIRS=(
|
|
38
|
+
".claude/agents"
|
|
39
|
+
".claude/commands"
|
|
40
|
+
".claude/skills"
|
|
41
|
+
".claude/docs"
|
|
42
|
+
".claude/docs/standards"
|
|
43
|
+
".claude/docs/workflows"
|
|
44
|
+
".claude/docs/diagrams"
|
|
45
|
+
".claude/docs/learnings"
|
|
46
|
+
".claude/schemas"
|
|
47
|
+
".claude/scripts"
|
|
48
|
+
".claude/sessions"
|
|
49
|
+
".claude/sessions/planning"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
for dir in "${REQUIRED_DIRS[@]}"; do
|
|
53
|
+
if [ ! -d "$dir" ]; then
|
|
54
|
+
error "Missing directory: $dir"
|
|
55
|
+
else
|
|
56
|
+
success "Directory exists: $dir"
|
|
57
|
+
fi
|
|
58
|
+
done
|
|
59
|
+
|
|
60
|
+
echo ""
|
|
61
|
+
echo "📄 Checking required files..."
|
|
62
|
+
|
|
63
|
+
REQUIRED_FILES=(
|
|
64
|
+
"CLAUDE.md"
|
|
65
|
+
".claude/docs/INDEX.md"
|
|
66
|
+
".claude/docs/quick-start.md"
|
|
67
|
+
".claude/docs/glossary.md"
|
|
68
|
+
".claude/agents/README.md"
|
|
69
|
+
".claude/commands/README.md"
|
|
70
|
+
".claude/skills/README.md"
|
|
71
|
+
".claude/scripts/health-check.sh"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
for file in "${REQUIRED_FILES[@]}"; do
|
|
75
|
+
if [ ! -f "$file" ]; then
|
|
76
|
+
error "Missing file: $file"
|
|
77
|
+
else
|
|
78
|
+
success "File exists: $file"
|
|
79
|
+
fi
|
|
80
|
+
done
|
|
81
|
+
|
|
82
|
+
echo ""
|
|
83
|
+
echo "🔢 Checking file counts..."
|
|
84
|
+
|
|
85
|
+
# Count agents (excluding README.md)
|
|
86
|
+
AGENT_COUNT=$(find .claude/agents -name "*.md" -type f ! -name "README.md" | wc -l)
|
|
87
|
+
echo " Agents: $AGENT_COUNT (expected: 13)"
|
|
88
|
+
if [ "$AGENT_COUNT" -ne 13 ]; then
|
|
89
|
+
warning "Agent count mismatch"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# Count commands (excluding README.md)
|
|
93
|
+
COMMAND_COUNT=$(find .claude/commands -name "*.md" -type f ! -name "README.md" | wc -l)
|
|
94
|
+
echo " Commands: $COMMAND_COUNT (expected: 16)"
|
|
95
|
+
if [ "$COMMAND_COUNT" -ne 16 ]; then
|
|
96
|
+
warning "Command count mismatch"
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
# Count skills (excluding README.md)
|
|
100
|
+
SKILL_COUNT=$(find .claude/skills -name "*.md" -type f ! -name "README.md" | wc -l)
|
|
101
|
+
echo " Skills: $SKILL_COUNT (expected: 16)"
|
|
102
|
+
if [ "$SKILL_COUNT" -ne 16 ]; then
|
|
103
|
+
warning "Skill count mismatch"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# Count workflows (excluding README.md)
|
|
107
|
+
WORKFLOW_COUNT=$(find .claude/docs/workflows -name "*.md" -type f ! -name "README.md" | wc -l)
|
|
108
|
+
echo " Workflows: $WORKFLOW_COUNT (expected: 9)"
|
|
109
|
+
if [ "$WORKFLOW_COUNT" -ne 9 ]; then
|
|
110
|
+
warning "Workflow count mismatch"
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# Count diagrams
|
|
114
|
+
DIAGRAM_COUNT=$(find .claude/docs/diagrams -name "*.mmd" -type f | wc -l)
|
|
115
|
+
echo " Diagrams: $DIAGRAM_COUNT (expected: 4)"
|
|
116
|
+
if [ "$DIAGRAM_COUNT" -ne 4 ]; then
|
|
117
|
+
warning "Diagram count mismatch"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# Count learnings (excluding README.md)
|
|
121
|
+
LEARNING_COUNT=$(find .claude/docs/learnings -name "*.md" -type f ! -name "README.md" | wc -l)
|
|
122
|
+
echo " Learnings: $LEARNING_COUNT (expected: 8)"
|
|
123
|
+
if [ "$LEARNING_COUNT" -ne 8 ]; then
|
|
124
|
+
warning "Learning count mismatch"
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
# Count schemas
|
|
128
|
+
SCHEMA_COUNT=$(find .claude/schemas -name "*.schema.json" -type f 2>/dev/null | wc -l)
|
|
129
|
+
echo " Schemas: $SCHEMA_COUNT (expected: 7)"
|
|
130
|
+
if [ "$SCHEMA_COUNT" -ne 7 ]; then
|
|
131
|
+
warning "Schema count mismatch"
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
echo ""
|
|
135
|
+
echo "🔐 Checking script permissions..."
|
|
136
|
+
|
|
137
|
+
SCRIPTS=(
|
|
138
|
+
".claude/scripts/health-check.sh"
|
|
139
|
+
".claude/scripts/validate-structure.sh"
|
|
140
|
+
".claude/scripts/validate-docs.sh"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
for script in "${SCRIPTS[@]}"; do
|
|
144
|
+
if [ -f "$script" ]; then
|
|
145
|
+
if [ -x "$script" ]; then
|
|
146
|
+
success "Executable: $script"
|
|
147
|
+
else
|
|
148
|
+
warning "Not executable: $script (run: chmod +x $script)"
|
|
149
|
+
fi
|
|
150
|
+
fi
|
|
151
|
+
done
|
|
152
|
+
|
|
153
|
+
echo ""
|
|
154
|
+
echo "📊 Summary"
|
|
155
|
+
echo "=========="
|
|
156
|
+
if [ $ERRORS -eq 0 ] && [ $WARNINGS -eq 0 ]; then
|
|
157
|
+
success "All structure validation checks passed!"
|
|
158
|
+
exit 0
|
|
159
|
+
elif [ $ERRORS -eq 0 ]; then
|
|
160
|
+
warning "$WARNINGS warnings found"
|
|
161
|
+
exit 0
|
|
162
|
+
else
|
|
163
|
+
error "$ERRORS errors and $WARNINGS warnings found"
|
|
164
|
+
exit 1
|
|
165
|
+
fi
|