Validates dashboard architecture for Tailwind v4 compliance, Next.js App Router structure, @policyengine/ui-kit integration, bun package manager usage, Tailwind classes, and custom-modal backend.
From essentialnpx claudepluginhub policyengine/policyengine-claude --plugin data-sciencesonnetGenerates SEO-optimized meta titles, descriptions, and URLs with character compliance, keyword strategies, emotional triggers, and CTAs. Provides A/B variations, schema markup, and setups for Next.js, Astro, WordPress.
Optimizes content for featured snippets and SERP features. Formats question-based content into direct-answer paragraphs, lists, tables, PAA pairs, FAQ schemas, and position-zero strategies.
SEO agent that analyzes keyword density in content, identifies primary/secondary keywords and entities, generates 20-30 LSI/semantic variations, and provides optimization checklists to prevent over-optimization.
Checks that the dashboard uses the correct framework, styling infrastructure, and package manager.
Skill: policyengine-frontend-builder-spec-skillSkill: policyengine-parameter-patterns-skill (if data_pattern: custom-modal)After loading the skill, extract every MUST / MUST NOT statement and validate each one.
Required:
# globals.css has @import "tailwindcss"
grep -n '@import.*tailwindcss' app/globals.css
# globals.css imports ui-kit theme
grep -n '@policyengine/ui-kit/theme.css' app/globals.css
# tailwindcss in package.json
grep '"tailwindcss"' package.json
# postcss.config.mjs exists with @tailwindcss/postcss
test -f postcss.config.mjs && grep '@tailwindcss/postcss' postcss.config.mjs
# @tailwindcss/postcss in package.json devDependencies
grep '@tailwindcss/postcss' package.json
Prohibited:
# No tailwind.config.ts/js
test ! -f tailwind.config.ts && test ! -f tailwind.config.js
# No old-style postcss.config.js (must be .mjs with @tailwindcss/postcss)
test ! -f postcss.config.js
# No @tailwind directives
grep -rn '@tailwind' app/ --include='*.css'
# No CSS module files
find . -name '*.module.css' -not -path './node_modules/*' -not -path './.next/*'
# No plain CSS files besides globals.css
find . -name '*.css' -not -name 'globals.css' -not -path './node_modules/*' -not -path './.next/*'
Required:
ls app/layout.tsx
ls app/page.tsx
grep '"next"' package.json
Prohibited:
# No Vite
test ! -f vite.config.ts && test ! -f vite.config.js
# No Pages Router
test ! -d pages
# In package.json
grep '@policyengine/ui-kit' package.json
# Actually imported in components
grep -rn "from '@policyengine/ui-kit'" app/ components/ --include='*.tsx' --include='*.ts'
# No CDN link for design-system
grep -rn 'unpkg.com/@policyengine/design-system' app/ --include='*.tsx'
# bun.lock exists
test -f bun.lock
# No package-lock.json
test ! -f package-lock.json
# Verify className attributes exist in components
grep -rn 'className=' components/ app/ --include='*.tsx' | head -20
Only run this check if plan.yaml has data_pattern: custom-modal. Skip entirely for other patterns.
This validates the three-file backend structure that mirrors policyengine-api-v2's simulation service and prevents module-level import crash-loops.
Required files:
test -f backend/_image_setup.py && echo "PASS" || echo "FAIL: _image_setup.py missing"
test -f backend/app.py && echo "PASS" || echo "FAIL: app.py missing"
test -f backend/simulation.py && echo "PASS" || echo "FAIL: simulation.py missing"
test -f backend/modal_app.py && echo "PASS" || echo "FAIL: modal_app.py missing"
_image_setup.py must have NO module-level policyengine/pydantic imports:
grep -n '^from policyengine\|^import policyengine\|^from pydantic\|^import pydantic' backend/_image_setup.py
# Should find NOTHING — all imports must be inside function bodies
app.py must have NO module-level policyengine/pydantic imports:
grep -n '^from policyengine\|^import policyengine\|^from pydantic\|^import pydantic' backend/app.py
# Should find NOTHING — only `modal` at module level
app.py must use .run_function for image snapshot:
grep -n 'run_function' backend/app.py
# Should find the snapshot call
app.py must include pydantic in pip_install (simulation.py uses it at module level):
grep -n 'pydantic' backend/app.py
# Should find "pydantic" in the .pip_install() call
app.py must include add_local_file for simulation.py (not auto-mounted):
grep -n 'add_local_file.*simulation' backend/app.py
# Should find the .add_local_file() call — Modal only auto-mounts module-level imports
simulation.py must have policyengine imports at module level (snapshotted):
grep -n '^from policyengine\|^import policyengine' backend/simulation.py
# Should find at least one import
Gateway must NOT include policyengine:
grep -n 'policyengine' backend/modal_app.py
# Should find NOTHING — gateway is lightweight
Only run this check if plan.yaml has data_pattern: custom-modal. Skip entirely for other patterns.
This validates that all parameter paths used in Reform.from_dict() or reform dictionaries in backend/simulation.py resolve to real parameters in the policyengine parameter tree.
Load required skill first: Skill: policyengine-parameter-patterns-skill — see section 6.5 for bracket path syntax rules.
Step 1: Extract all parameter paths from simulation.py:
# Find all string literals that look like parameter paths (gov.xxx.yyy)
grep -oP '"gov\.[a-z_.]+(\[[A-Z_0-9]+\])*(\.[a-z_]+)*"' backend/simulation.py | sort -u
# Also check for f-string patterns building paths
grep -n 'gov\.' backend/simulation.py | grep -v '#'
Step 2: For each parameter path, find and verify the YAML source:
# Convert a dotted path like gov.irs.income.bracket.rates to a file search
# The YAML file is at parameters/gov/irs/income/bracket.yaml with rates as a child node
Step 3: Check indexing correctness:
1:, 2:, 3:, ...): verify the code uses those exact indices, NOT 0-basedbrackets: list: verify the code uses 0-based indices WITH .amount or .rate sub-key[SINGLE], [JOINT], etc.Step 4: Verify programmatically (preferred):
# If policyengine-us is installed locally (e.g., in backend/):
cd backend && uv run python3 -c "
from policyengine_us import CountryTaxBenefitSystem
p = CountryTaxBenefitSystem().parameters
# Test each path — will raise ParameterNotFoundError if wrong
paths_to_check = [
# Paste extracted paths here
]
for path in paths_to_check:
try:
node = p
# Navigate the path
# ... (manual or eval-based traversal)
print(f'PASS: {path}')
except Exception as e:
print(f'FAIL: {path} — {e}')
"
Common failures to flag:
rates[0] when the YAML uses 1-indexed keys (1: through 7:) → FAILeitc.max[0] without .amount suffix on a bracket scale → FAILrates[0] without .rate suffix on a bracket scale → FAIL[SINGLE]/[JOINT] index → FAIL## Architecture Compliance Report
### Summary
- PASS: X/7 checks (or X/5 if not custom-modal)
- FAIL: Y checks
### Results
| # | Check | Status | Evidence |
|---|-------|--------|----------|
| 1 | Tailwind CSS v4 | PASS/FAIL | ... |
| 2 | Next.js App Router | PASS/FAIL | ... |
| 3 | ui-kit integration | PASS/FAIL | ... |
| 4 | Package manager | PASS/FAIL | ... |
| 5 | Tailwind classes used | PASS/FAIL | ... |
| 6 | Modal backend structure | PASS/FAIL/SKIP | ... |
| 7 | Parameter path verification | PASS/FAIL/SKIP | ... |
### Failures (if any)
#### Check N: [name]
- **Found**: [violation]
- **Expected**: [correct approach]
- **Fix**: [specific action]