@bookedsolid/reagent 0.5.0 → 0.7.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/agents/ai-platforms/ai-deepseek-specialist.md +83 -0
- package/agents/ai-platforms/ai-elevenlabs-specialist.md +75 -0
- package/agents/ai-platforms/ai-grok-specialist.md +71 -0
- package/agents/ai-platforms/ai-local-llm-specialist.md +95 -0
- package/agents/ai-platforms/ai-video-ai-specialist.md +103 -0
- package/agents/engineering/cto-advisory.md +44 -0
- package/agents/engineering/qa-engineer-automation.md +77 -0
- package/agents/engineering/qa-engineer-manual.md +48 -0
- package/agents/engineering/qa-lead.md +124 -0
- package/agents/engineering/security-engineer-appsec.md +47 -0
- package/agents/engineering/security-engineer-compliance.md +47 -0
- package/dist/cli/commands/catalyze/gap-detector.d.ts +6 -0
- package/dist/cli/commands/catalyze/gap-detector.d.ts.map +1 -0
- package/dist/cli/commands/catalyze/gap-detector.js +359 -0
- package/dist/cli/commands/catalyze/gap-detector.js.map +1 -0
- package/dist/cli/commands/catalyze/index.d.ts +15 -0
- package/dist/cli/commands/catalyze/index.d.ts.map +1 -0
- package/dist/cli/commands/catalyze/index.js +149 -0
- package/dist/cli/commands/catalyze/index.js.map +1 -0
- package/dist/cli/commands/catalyze/report-generator.d.ts +17 -0
- package/dist/cli/commands/catalyze/report-generator.d.ts.map +1 -0
- package/dist/cli/commands/catalyze/report-generator.js +290 -0
- package/dist/cli/commands/catalyze/report-generator.js.map +1 -0
- package/dist/cli/commands/catalyze/stack-analyzer.d.ts +6 -0
- package/dist/cli/commands/catalyze/stack-analyzer.d.ts.map +1 -0
- package/dist/cli/commands/catalyze/stack-analyzer.js +267 -0
- package/dist/cli/commands/catalyze/stack-analyzer.js.map +1 -0
- package/dist/cli/commands/catalyze/types.d.ts +40 -0
- package/dist/cli/commands/catalyze/types.d.ts.map +1 -0
- package/dist/cli/commands/catalyze/types.js +2 -0
- package/dist/cli/commands/catalyze/types.js.map +1 -0
- package/dist/cli/commands/init/agents.d.ts.map +1 -1
- package/dist/cli/commands/init/agents.js +9 -0
- package/dist/cli/commands/init/agents.js.map +1 -1
- package/dist/cli/commands/init/claude-hooks.d.ts.map +1 -1
- package/dist/cli/commands/init/claude-hooks.js +27 -0
- package/dist/cli/commands/init/claude-hooks.js.map +1 -1
- package/dist/cli/commands/init/commands.d.ts.map +1 -1
- package/dist/cli/commands/init/commands.js +9 -0
- package/dist/cli/commands/init/commands.js.map +1 -1
- package/dist/cli/commands/init/discord.d.ts +21 -0
- package/dist/cli/commands/init/discord.d.ts.map +1 -0
- package/dist/cli/commands/init/discord.js +87 -0
- package/dist/cli/commands/init/discord.js.map +1 -0
- package/dist/cli/commands/init/github.d.ts +13 -0
- package/dist/cli/commands/init/github.d.ts.map +1 -0
- package/dist/cli/commands/init/github.js +81 -0
- package/dist/cli/commands/init/github.js.map +1 -0
- package/dist/cli/commands/init/index.d.ts.map +1 -1
- package/dist/cli/commands/init/index.js +72 -17
- package/dist/cli/commands/init/index.js.map +1 -1
- package/dist/cli/commands/init/profiles.d.ts +39 -0
- package/dist/cli/commands/init/profiles.d.ts.map +1 -0
- package/dist/cli/commands/init/profiles.js +132 -0
- package/dist/cli/commands/init/profiles.js.map +1 -0
- package/dist/cli/index.js +27 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/gateway/native-tools.d.ts.map +1 -1
- package/dist/gateway/native-tools.js +63 -0
- package/dist/gateway/native-tools.js.map +1 -1
- package/dist/pm/discord-notifier.d.ts +52 -0
- package/dist/pm/discord-notifier.d.ts.map +1 -0
- package/dist/pm/discord-notifier.js +122 -0
- package/dist/pm/discord-notifier.js.map +1 -0
- package/dist/pm/github-bridge.d.ts +35 -0
- package/dist/pm/github-bridge.d.ts.map +1 -1
- package/dist/pm/github-bridge.js +185 -0
- package/dist/pm/github-bridge.js.map +1 -1
- package/dist/pm/types.d.ts +7 -7
- package/hooks/ci-config-protection.sh +84 -0
- package/hooks/file-size-guard.sh +64 -0
- package/hooks/git-config-guard.sh +81 -0
- package/hooks/import-guard.sh +99 -0
- package/hooks/network-exfil-guard.sh +118 -0
- package/hooks/output-validation.sh +101 -0
- package/hooks/rate-limit-guard.sh +75 -0
- package/hooks/symlink-guard.sh +96 -0
- package/package.json +1 -1
- package/profiles/astro/README.md +44 -0
- package/profiles/astro/agents.txt +3 -0
- package/profiles/astro/gates.yaml +15 -0
- package/profiles/astro/hooks/astro-ssr-guard.sh +73 -0
- package/profiles/drupal/README.md +53 -0
- package/profiles/drupal/agents.txt +4 -0
- package/profiles/drupal/gates.yaml +15 -0
- package/profiles/drupal/hooks/drupal-coding-standards.sh +70 -0
- package/profiles/drupal/hooks/hook-update-guard.sh +65 -0
- package/profiles/lit-wc/README.md +48 -0
- package/profiles/lit-wc/agents.txt +4 -0
- package/profiles/lit-wc/gates.yaml +15 -0
- package/profiles/lit-wc/hooks/cem-integrity-gate.sh +48 -0
- package/profiles/lit-wc/hooks/shadow-dom-guard.sh +76 -0
- package/profiles/nextjs/README.md +44 -0
- package/profiles/nextjs/agents.txt +4 -0
- package/profiles/nextjs/gates.yaml +15 -0
- package/profiles/nextjs/hooks/server-component-drift.sh +73 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# astro profile
|
|
2
|
+
|
|
3
|
+
Reagent profile for projects built with [Astro](https://astro.build/) (v3+, including v5).
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
Install this profile when your project:
|
|
8
|
+
|
|
9
|
+
- Is built with Astro (any rendering mode: SSG, SSR, hybrid)
|
|
10
|
+
- Uses Astro components (`.astro` files)
|
|
11
|
+
- Has island-architecture client components (React, Vue, Svelte, Lit, etc.)
|
|
12
|
+
- Uses `astro check` and `astro build` as quality gates
|
|
13
|
+
|
|
14
|
+
## What this profile installs
|
|
15
|
+
|
|
16
|
+
### Hooks
|
|
17
|
+
|
|
18
|
+
- **astro-ssr-guard.sh** — PostToolUse/Write: warns on React hooks used in `.astro` frontmatter without a `client:*` directive, and `document`/`window` access in SSR context (frontmatter runs server-side).
|
|
19
|
+
|
|
20
|
+
### Quality gates (gates.yaml)
|
|
21
|
+
|
|
22
|
+
| Gate | Command | On failure |
|
|
23
|
+
| ---------------- | ------------------ | ---------- |
|
|
24
|
+
| astro-check | `npx astro check` | block |
|
|
25
|
+
| astro-build | `npx astro build` | block |
|
|
26
|
+
| astro-type-check | `npx tsc --noEmit` | block |
|
|
27
|
+
|
|
28
|
+
### Agents
|
|
29
|
+
|
|
30
|
+
- `astro-specialist` — Astro architecture, islands, content collections
|
|
31
|
+
- `frontend-specialist` — general frontend and component patterns
|
|
32
|
+
- `performance-engineer` — Core Web Vitals, Astro partial hydration strategies
|
|
33
|
+
|
|
34
|
+
## Recommended additions
|
|
35
|
+
|
|
36
|
+
- Playwright e2e tests for rendered pages
|
|
37
|
+
- `@astrojs/check` for enhanced type checking
|
|
38
|
+
- Lighthouse CI for CWV regression on static output
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
reagent init --profile astro
|
|
44
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
gates:
|
|
2
|
+
- name: astro-check
|
|
3
|
+
command: npx astro check
|
|
4
|
+
description: Astro type checking must pass (catches SSR/component errors)
|
|
5
|
+
on_failure: block
|
|
6
|
+
|
|
7
|
+
- name: astro-build
|
|
8
|
+
command: npx astro build
|
|
9
|
+
description: Astro production build must succeed
|
|
10
|
+
on_failure: block
|
|
11
|
+
|
|
12
|
+
- name: astro-type-check
|
|
13
|
+
command: npx tsc --noEmit
|
|
14
|
+
description: TypeScript must compile without errors
|
|
15
|
+
on_failure: block
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# profiles/astro/hooks/astro-ssr-guard.sh
|
|
3
|
+
# PostToolUse hook for Write — warns on Astro SSR anti-patterns in .astro files.
|
|
4
|
+
# Checks for: React hooks in non-client context, document/window in frontmatter.
|
|
5
|
+
# Advisory only — exits 0 after printing warnings.
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
10
|
+
LIB="$HOOK_DIR/../../../hooks/_lib/common.sh"
|
|
11
|
+
if [[ -f "$LIB" ]]; then
|
|
12
|
+
source "$LIB"
|
|
13
|
+
check_halt
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
INPUT=$(cat)
|
|
17
|
+
TOOL_NAME=$(printf '%s' "$INPUT" | grep -o '"tool_name":"[^"]*"' | head -1 | cut -d'"' -f4 2>/dev/null || echo "")
|
|
18
|
+
FILE_PATH=$(printf '%s' "$INPUT" | grep -o '"path":"[^"]*"' | head -1 | cut -d'"' -f4 2>/dev/null || echo "")
|
|
19
|
+
|
|
20
|
+
if [[ "$TOOL_NAME" != "Write" && "$TOOL_NAME" != "Edit" ]]; then
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Only target .astro files
|
|
25
|
+
case "$FILE_PATH" in
|
|
26
|
+
*.astro) ;;
|
|
27
|
+
*) exit 0 ;;
|
|
28
|
+
esac
|
|
29
|
+
|
|
30
|
+
if [[ ! -f "$FILE_PATH" ]]; then
|
|
31
|
+
exit 0
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
CONTENT=$(cat "$FILE_PATH" 2>/dev/null || echo "")
|
|
35
|
+
WARNINGS=()
|
|
36
|
+
|
|
37
|
+
# Extract frontmatter (between --- delimiters)
|
|
38
|
+
FRONTMATTER=""
|
|
39
|
+
if printf '%s' "$CONTENT" | grep -q '^---'; then
|
|
40
|
+
FRONTMATTER=$(printf '%s' "$CONTENT" | awk '/^---/{if(f)exit; f=1; next} f{print}')
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Check 1: React hooks in .astro files — only valid in client:* components
|
|
44
|
+
if printf '%s' "$CONTENT" | grep -qE '\b(useState|useEffect|useContext|useReducer|useCallback|useMemo|useRef)\s*[(<(]'; then
|
|
45
|
+
# Check if it's inside a component tag with client: directive
|
|
46
|
+
if ! printf '%s' "$CONTENT" | grep -qE 'client:(load|idle|visible|media|only)'; then
|
|
47
|
+
WARNINGS+=("ASTRO SSR: React hook (useState/useEffect/etc.) found but no 'client:*' directive detected in this file. React hooks only run in client-rendered components. Add 'client:load' (or other hydration strategy) to the component tag, or move hooks to a .tsx component used with 'client:load'.")
|
|
48
|
+
fi
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# Check 2: document or window in frontmatter (SSR context — not available server-side)
|
|
52
|
+
if [[ -n "$FRONTMATTER" ]]; then
|
|
53
|
+
if printf '%s' "$FRONTMATTER" | grep -qE '\b(document|window)\b'; then
|
|
54
|
+
WARNINGS+=("ASTRO SSR: 'document' or 'window' accessed in Astro frontmatter (the --- block). Frontmatter runs at build time / server-side where these globals are not available. Move browser API calls into a <script> tag or a client:* component.")
|
|
55
|
+
fi
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# Check 3: import of useState/useEffect at top of frontmatter without client usage
|
|
59
|
+
if printf '%s' "$FRONTMATTER" | grep -qE "import.*\{.*(useState|useEffect).*\}.*from\s+['\"]react['\"]"; then
|
|
60
|
+
if ! printf '%s' "$CONTENT" | grep -qE 'client:(load|idle|visible|media|only)'; then
|
|
61
|
+
WARNINGS+=("ASTRO SSR: React state/effect hooks imported in frontmatter without a 'client:*' component. This import will likely cause an error at runtime in SSR mode.")
|
|
62
|
+
fi
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
if [[ ${#WARNINGS[@]} -gt 0 ]]; then
|
|
66
|
+
printf '\n[astro-ssr-guard] Astro SSR advisory warnings for %s:\n' "$FILE_PATH" >&2
|
|
67
|
+
for warning in "${WARNINGS[@]}"; do
|
|
68
|
+
printf ' WARN: %s\n' "$warning" >&2
|
|
69
|
+
done
|
|
70
|
+
printf '\n' >&2
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
exit 0
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# drupal profile
|
|
2
|
+
|
|
3
|
+
Reagent profile for Drupal CMS projects (Drupal 9/10/11).
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
Install this profile when your project:
|
|
8
|
+
|
|
9
|
+
- Is built on Drupal (any modern version)
|
|
10
|
+
- Uses custom modules or themes
|
|
11
|
+
- Has update hooks (`.install` files)
|
|
12
|
+
- Requires Drupal coding standards enforcement
|
|
13
|
+
|
|
14
|
+
## What this profile installs
|
|
15
|
+
|
|
16
|
+
### Hooks
|
|
17
|
+
|
|
18
|
+
- **drupal-coding-standards.sh** — PostToolUse/Write: warns on raw superglobals (`$_GET`, `$_POST`), hardcoded entity IDs, `hook_update_N` without schema management, and `t()` string concatenation.
|
|
19
|
+
- **hook-update-guard.sh** — PostToolUse/Write: guards `.install` files for destructive schema operations and update hook numbering gaps.
|
|
20
|
+
|
|
21
|
+
### Quality gates (gates.yaml)
|
|
22
|
+
|
|
23
|
+
| Gate | Command | On failure |
|
|
24
|
+
| -------------------- | ------------------------------------- | ---------- |
|
|
25
|
+
| phpcs-drupal | `vendor/bin/phpcs --standard=Drupal` | block |
|
|
26
|
+
| drupal-cache-rebuild | `vendor/bin/drush cr` | warn |
|
|
27
|
+
| phpunit-drupal | `vendor/bin/phpunit --testsuite=unit` | block |
|
|
28
|
+
|
|
29
|
+
### Agents
|
|
30
|
+
|
|
31
|
+
- `drupal-specialist` — Drupal architecture and module development
|
|
32
|
+
- `drupal-integration-specialist` — third-party integrations (APIs, payment, CRM)
|
|
33
|
+
- `backend-engineer-payments` — commerce and payment flows
|
|
34
|
+
- `security-engineer` — Drupal security review
|
|
35
|
+
|
|
36
|
+
## Recommended additions
|
|
37
|
+
|
|
38
|
+
- Behat behavioral tests for content workflows
|
|
39
|
+
- Playwright e2e for rendered frontend
|
|
40
|
+
- `phpstan` with Drupal extension for static analysis
|
|
41
|
+
|
|
42
|
+
## Prerequisites
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
composer require --dev drupal/coder
|
|
46
|
+
./vendor/bin/phpcs --config-set installed_paths vendor/drupal/coder/coder_sniffer
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
reagent init --profile drupal
|
|
53
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
gates:
|
|
2
|
+
- name: phpcs-drupal
|
|
3
|
+
command: vendor/bin/phpcs --standard=Drupal --extensions=php,module,inc,install,theme .
|
|
4
|
+
description: Drupal coding standards (PHPCS) must pass
|
|
5
|
+
on_failure: block
|
|
6
|
+
|
|
7
|
+
- name: drupal-cache-rebuild
|
|
8
|
+
command: vendor/bin/drush cr
|
|
9
|
+
description: Drush cache rebuild must succeed (validates module/theme structure)
|
|
10
|
+
on_failure: warn
|
|
11
|
+
|
|
12
|
+
- name: phpunit-drupal
|
|
13
|
+
command: vendor/bin/phpunit --testsuite=unit
|
|
14
|
+
description: Drupal PHPUnit unit tests must pass
|
|
15
|
+
on_failure: block
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# profiles/drupal/hooks/drupal-coding-standards.sh
|
|
3
|
+
# PostToolUse hook for Write — warns on Drupal anti-patterns in PHP/module/theme files.
|
|
4
|
+
# Checks for: raw superglobals, hardcoded entity IDs, hook_update_N without schema bump.
|
|
5
|
+
# Advisory only — exits 0 after printing warnings.
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
10
|
+
LIB="$HOOK_DIR/../../../hooks/_lib/common.sh"
|
|
11
|
+
if [[ -f "$LIB" ]]; then
|
|
12
|
+
source "$LIB"
|
|
13
|
+
check_halt
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
INPUT=$(cat)
|
|
17
|
+
TOOL_NAME=$(printf '%s' "$INPUT" | grep -o '"tool_name":"[^"]*"' | head -1 | cut -d'"' -f4 2>/dev/null || echo "")
|
|
18
|
+
FILE_PATH=$(printf '%s' "$INPUT" | grep -o '"path":"[^"]*"' | head -1 | cut -d'"' -f4 2>/dev/null || echo "")
|
|
19
|
+
|
|
20
|
+
if [[ "$TOOL_NAME" != "Write" && "$TOOL_NAME" != "Edit" ]]; then
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Only target Drupal PHP files
|
|
25
|
+
if [[ -z "$FILE_PATH" ]]; then
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
28
|
+
case "$FILE_PATH" in
|
|
29
|
+
*.php|*.module|*.theme|*.install) ;;
|
|
30
|
+
*) exit 0 ;;
|
|
31
|
+
esac
|
|
32
|
+
|
|
33
|
+
if [[ ! -f "$FILE_PATH" ]]; then
|
|
34
|
+
exit 0
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
CONTENT=$(cat "$FILE_PATH" 2>/dev/null || echo "")
|
|
38
|
+
WARNINGS=()
|
|
39
|
+
|
|
40
|
+
# Check 1: Raw superglobal access — should use \Drupal::request()
|
|
41
|
+
if printf '%s' "$CONTENT" | grep -qE '\$_(GET|POST|REQUEST|SERVER)\['; then
|
|
42
|
+
WARNINGS+=("DRUPAL: Direct superglobal access (\$_GET, \$_POST, \$_REQUEST, \$_SERVER) detected. Use \\Drupal::request()->query->get() or \\Drupal::request()->request->get() for proper sanitization and testability.")
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# Check 2: Hardcoded numeric node/entity IDs in templates or module files
|
|
46
|
+
if printf '%s' "$CONTENT" | grep -qE "(Node::load|\\\\Drupal::entityTypeManager\(\)->getStorage\('node'\)->load\(|nid\s*=\s*[0-9]+|->load\([0-9]+\))"; then
|
|
47
|
+
WARNINGS+=("DRUPAL: Hardcoded numeric entity/node ID detected. Use configuration, a content reference field, or \Drupal::config() instead of load(42) — hardcoded IDs break between environments.")
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Check 3: hook_update_N without schema version bump check
|
|
51
|
+
if printf '%s' "$CONTENT" | grep -qE 'function [a-z_]+_update_[0-9]+'; then
|
|
52
|
+
if ! printf '%s' "$CONTENT" | grep -qE 'schema_version|hook_update_dependencies|db_change_table|Schema::'; then
|
|
53
|
+
WARNINGS+=("DRUPAL: hook_update_N() found without apparent schema version management. Ensure \$sandbox['#finished'] logic is correct for batched updates, and verify schema version alignment via hook_update_dependencies() if needed.")
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Check 4: t() with concatenated strings (breaks localization)
|
|
58
|
+
if printf '%s' "$CONTENT" | grep -qE "t\(['\"].*\\\$[a-zA-Z_]|t\(['\"].*'\s*\.\s*\\\$"; then
|
|
59
|
+
WARNINGS+=("DRUPAL: String concatenation inside t() detected. Use placeholders ('@var', '%var', ':url') instead: t('Hello @name', ['@name' => \$name]). Concatenation breaks translation extraction.")
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
if [[ ${#WARNINGS[@]} -gt 0 ]]; then
|
|
63
|
+
printf '\n[drupal-coding-standards] Advisory warnings for %s:\n' "$FILE_PATH" >&2
|
|
64
|
+
for warning in "${WARNINGS[@]}"; do
|
|
65
|
+
printf ' WARN: %s\n' "$warning" >&2
|
|
66
|
+
done
|
|
67
|
+
printf '\n' >&2
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
exit 0
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# profiles/drupal/hooks/hook-update-guard.sh
|
|
3
|
+
# PostToolUse hook for Write — additional guard for hook_update_N patterns.
|
|
4
|
+
# Specifically watches .install files for update hooks that modify critical schema.
|
|
5
|
+
# Advisory only — exits 0 after printing warnings.
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
10
|
+
LIB="$HOOK_DIR/../../../hooks/_lib/common.sh"
|
|
11
|
+
if [[ -f "$LIB" ]]; then
|
|
12
|
+
source "$LIB"
|
|
13
|
+
check_halt
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
INPUT=$(cat)
|
|
17
|
+
TOOL_NAME=$(printf '%s' "$INPUT" | grep -o '"tool_name":"[^"]*"' | head -1 | cut -d'"' -f4 2>/dev/null || echo "")
|
|
18
|
+
FILE_PATH=$(printf '%s' "$INPUT" | grep -o '"path":"[^"]*"' | head -1 | cut -d'"' -f4 2>/dev/null || echo "")
|
|
19
|
+
|
|
20
|
+
if [[ "$TOOL_NAME" != "Write" && "$TOOL_NAME" != "Edit" ]]; then
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Only target .install files
|
|
25
|
+
case "$FILE_PATH" in
|
|
26
|
+
*.install) ;;
|
|
27
|
+
*) exit 0 ;;
|
|
28
|
+
esac
|
|
29
|
+
|
|
30
|
+
if [[ ! -f "$FILE_PATH" ]]; then
|
|
31
|
+
exit 0
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
CONTENT=$(cat "$FILE_PATH" 2>/dev/null || echo "")
|
|
35
|
+
WARNINGS=()
|
|
36
|
+
|
|
37
|
+
# Check: db_drop_table / db_drop_field without backup advisory
|
|
38
|
+
if printf '%s' "$CONTENT" | grep -qE 'db_drop_(table|field)\s*\('; then
|
|
39
|
+
WARNINGS+=("DRUPAL SCHEMA: Destructive schema operation (db_drop_table/db_drop_field) detected in update hook. Ensure data migration or backup is handled before dropping. Consider using db_rename_table first if data needs preservation.")
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Check: Multiple update hooks in single file (numbering gaps)
|
|
43
|
+
UPDATE_HOOKS=$(printf '%s' "$CONTENT" | grep -oE 'function [a-z_]+_update_([0-9]+)' | grep -oE '[0-9]+$' | sort -n || echo "")
|
|
44
|
+
if [[ -n "$UPDATE_HOOKS" ]]; then
|
|
45
|
+
PREV=""
|
|
46
|
+
while IFS= read -r num; do
|
|
47
|
+
if [[ -n "$PREV" ]]; then
|
|
48
|
+
EXPECTED=$((PREV + 1))
|
|
49
|
+
if [[ "$num" -gt "$EXPECTED" ]]; then
|
|
50
|
+
WARNINGS+=("DRUPAL SCHEMA: Gap detected in update hook numbering (after $PREV, next is $num). Verify this is intentional — gaps can confuse module update ordering.")
|
|
51
|
+
fi
|
|
52
|
+
fi
|
|
53
|
+
PREV="$num"
|
|
54
|
+
done <<< "$UPDATE_HOOKS"
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
if [[ ${#WARNINGS[@]} -gt 0 ]]; then
|
|
58
|
+
printf '\n[hook-update-guard] Advisory warnings for %s:\n' "$FILE_PATH" >&2
|
|
59
|
+
for warning in "${WARNINGS[@]}"; do
|
|
60
|
+
printf ' WARN: %s\n' "$warning" >&2
|
|
61
|
+
done
|
|
62
|
+
printf '\n' >&2
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
exit 0
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# lit-wc profile
|
|
2
|
+
|
|
3
|
+
Reagent profile for projects using [Lit](https://lit.dev/) and native Web Components (Custom Elements v1, Shadow DOM).
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
Install this profile when your project:
|
|
8
|
+
|
|
9
|
+
- Uses `LitElement`, `ReactiveElement`, or plain `HTMLElement` subclasses
|
|
10
|
+
- Registers custom elements via `customElements.define()`
|
|
11
|
+
- Uses Shadow DOM for style encapsulation
|
|
12
|
+
- Uses the Custom Elements Manifest (`cem analyze`) for component documentation
|
|
13
|
+
|
|
14
|
+
## What this profile installs
|
|
15
|
+
|
|
16
|
+
### Hooks
|
|
17
|
+
|
|
18
|
+
- **shadow-dom-guard.sh** — PostToolUse/Write: warns on `document.querySelector` inside web components, missing `:host` CSS scoping, and `customElements.define()` without a guard check.
|
|
19
|
+
- **cem-integrity-gate.sh** — PostToolUse/Write: advisory reminder to regenerate `custom-elements.json` after component source changes.
|
|
20
|
+
|
|
21
|
+
### Quality gates (gates.yaml)
|
|
22
|
+
|
|
23
|
+
| Gate | Command | On failure |
|
|
24
|
+
| --------------- | -------------------- | ---------- |
|
|
25
|
+
| cem-analyze | `npx cem analyze` | block |
|
|
26
|
+
| web-test-runner | `npx wtr --coverage` | warn |
|
|
27
|
+
| lit-ts-check | `npx tsc --noEmit` | block |
|
|
28
|
+
|
|
29
|
+
### Agents
|
|
30
|
+
|
|
31
|
+
- `lit-specialist` — deep Lit/Web Components expertise
|
|
32
|
+
- `accessibility-engineer` — a11y for custom elements and ARIA
|
|
33
|
+
- `frontend-specialist` — general frontend patterns
|
|
34
|
+
- `design-system-developer` — design token and component API patterns
|
|
35
|
+
|
|
36
|
+
## Recommended additions
|
|
37
|
+
|
|
38
|
+
- Visual regression tests (Playwright snapshots or Storybook visual tests)
|
|
39
|
+
- `@axe-core/playwright` for accessibility audits per component
|
|
40
|
+
- `@web/test-runner-playwright` for real browser test execution
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
reagent init --profile lit-wc
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Or during initial setup when `reagent catalyze` detects Lit/Web Components usage.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
gates:
|
|
2
|
+
- name: cem-analyze
|
|
3
|
+
command: npx cem analyze
|
|
4
|
+
description: Custom Elements Manifest must be valid and up-to-date
|
|
5
|
+
on_failure: block
|
|
6
|
+
|
|
7
|
+
- name: web-test-runner
|
|
8
|
+
command: npx wtr --coverage
|
|
9
|
+
description: Web Test Runner component tests must pass
|
|
10
|
+
on_failure: warn
|
|
11
|
+
|
|
12
|
+
- name: lit-ts-check
|
|
13
|
+
command: npx tsc --noEmit
|
|
14
|
+
description: TypeScript must compile without errors
|
|
15
|
+
on_failure: block
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# profiles/lit-wc/hooks/cem-integrity-gate.sh
|
|
3
|
+
# PostToolUse hook for Write — verifies custom elements manifest stays parseable.
|
|
4
|
+
# If cem analyze is available and a custom-elements.json exists, validates it.
|
|
5
|
+
# Advisory only — exits 0 after printing warnings.
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
10
|
+
LIB="$HOOK_DIR/../../../hooks/_lib/common.sh"
|
|
11
|
+
if [[ -f "$LIB" ]]; then
|
|
12
|
+
source "$LIB"
|
|
13
|
+
check_halt
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
INPUT=$(cat)
|
|
17
|
+
TOOL_NAME=$(printf '%s' "$INPUT" | grep -o '"tool_name":"[^"]*"' | head -1 | cut -d'"' -f4 2>/dev/null || echo "")
|
|
18
|
+
FILE_PATH=$(printf '%s' "$INPUT" | grep -o '"path":"[^"]*"' | head -1 | cut -d'"' -f4 2>/dev/null || echo "")
|
|
19
|
+
|
|
20
|
+
if [[ "$TOOL_NAME" != "Write" && "$TOOL_NAME" != "Edit" ]]; then
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Only care about .ts/.js files (component source changes)
|
|
25
|
+
case "$FILE_PATH" in
|
|
26
|
+
*.ts|*.js) ;;
|
|
27
|
+
*) exit 0 ;;
|
|
28
|
+
esac
|
|
29
|
+
|
|
30
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
31
|
+
CEM_JSON="$PROJECT_DIR/custom-elements.json"
|
|
32
|
+
|
|
33
|
+
# Only run if a custom-elements.json exists
|
|
34
|
+
if [[ ! -f "$CEM_JSON" ]]; then
|
|
35
|
+
exit 0
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# Validate the existing manifest is valid JSON
|
|
39
|
+
if ! python3 -c "import sys,json; json.load(open('$CEM_JSON'))" 2>/dev/null && \
|
|
40
|
+
! node -e "require('$CEM_JSON')" 2>/dev/null; then
|
|
41
|
+
printf '[cem-integrity-gate] WARN: custom-elements.json exists but failed JSON validation. Run: npx cem analyze\n' >&2
|
|
42
|
+
exit 0
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# Advisory: remind to regenerate after component changes
|
|
46
|
+
printf '[cem-integrity-gate] Advisory: Component source changed. Remember to run "npx cem analyze" to keep custom-elements.json in sync.\n' >&2
|
|
47
|
+
|
|
48
|
+
exit 0
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# profiles/lit-wc/hooks/shadow-dom-guard.sh
|
|
3
|
+
# PostToolUse hook for Write — validates Shadow DOM usage patterns in Lit/Web Components.
|
|
4
|
+
# Warns on anti-patterns: direct document queries, missing :host scoping, unsafe customElements.define.
|
|
5
|
+
# Advisory only — exits 0 after printing warnings.
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
10
|
+
LIB="$HOOK_DIR/../../../hooks/_lib/common.sh"
|
|
11
|
+
if [[ -f "$LIB" ]]; then
|
|
12
|
+
# shellcheck source=hooks/_lib/common.sh
|
|
13
|
+
source "$LIB"
|
|
14
|
+
check_halt
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# Read tool input from stdin
|
|
18
|
+
INPUT=$(cat)
|
|
19
|
+
TOOL_NAME=$(printf '%s' "$INPUT" | grep -o '"tool_name":"[^"]*"' | head -1 | cut -d'"' -f4 2>/dev/null || echo "")
|
|
20
|
+
FILE_PATH=$(printf '%s' "$INPUT" | grep -o '"path":"[^"]*"' | head -1 | cut -d'"' -f4 2>/dev/null || echo "")
|
|
21
|
+
|
|
22
|
+
# Only run on Write tool
|
|
23
|
+
if [[ "$TOOL_NAME" != "Write" && "$TOOL_NAME" != "Edit" ]]; then
|
|
24
|
+
exit 0
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Only target .ts, .js files (web component source)
|
|
28
|
+
if [[ -z "$FILE_PATH" ]]; then
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
case "$FILE_PATH" in
|
|
32
|
+
*.ts|*.js) ;;
|
|
33
|
+
*) exit 0 ;;
|
|
34
|
+
esac
|
|
35
|
+
|
|
36
|
+
# Only warn if file exists (was just written)
|
|
37
|
+
if [[ ! -f "$FILE_PATH" ]]; then
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
CONTENT=$(cat "$FILE_PATH" 2>/dev/null || echo "")
|
|
42
|
+
WARNINGS=()
|
|
43
|
+
|
|
44
|
+
# Check 1: document.querySelector / document.getElementById inside HTMLElement/LitElement subclass
|
|
45
|
+
if printf '%s' "$CONTENT" | grep -qE 'extends\s+(HTMLElement|LitElement)'; then
|
|
46
|
+
if printf '%s' "$CONTENT" | grep -qE 'document\.(querySelector|getElementById|getElementsBy)'; then
|
|
47
|
+
WARNINGS+=("SHADOW DOM: 'document.querySelector/getElementById' found inside a web component. Use 'this.shadowRoot?.querySelector()' instead to avoid escaping the shadow boundary.")
|
|
48
|
+
fi
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# Check 2: CSS selectors without :host scoping (look for <style> or css`` template literals with bare selectors)
|
|
52
|
+
if printf '%s' "$CONTENT" | grep -qE "css\`[^$]*\`|<style>"; then
|
|
53
|
+
# Look for top-level selectors that are NOT :host or :root
|
|
54
|
+
if printf '%s' "$CONTENT" | grep -qE '^\s*(\.[\w-]+|#[\w-]+|\w+\s*\{)' && \
|
|
55
|
+
! printf '%s' "$CONTENT" | grep -qE '^\s*:host'; then
|
|
56
|
+
WARNINGS+=("SHADOW DOM: CSS without ':host' scoping detected. All styles in web components should be scoped via ':host { }' to prevent style leakage.")
|
|
57
|
+
fi
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Check 3: customElements.define without guard
|
|
61
|
+
if printf '%s' "$CONTENT" | grep -qE 'customElements\.define\('; then
|
|
62
|
+
if ! printf '%s' "$CONTENT" | grep -qE 'customElements\.get\(|!customElements\.get\('; then
|
|
63
|
+
WARNINGS+=("SHADOW DOM: 'customElements.define()' called without checking 'customElements.get(name)' first. This will throw if the element is defined twice (e.g., in tests or HMR). Guard with: if (!customElements.get('my-el')) customElements.define('my-el', MyEl)")
|
|
64
|
+
fi
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Print warnings as advisories
|
|
68
|
+
if [[ ${#WARNINGS[@]} -gt 0 ]]; then
|
|
69
|
+
printf '\n[shadow-dom-guard] Web Component advisory warnings for %s:\n' "$FILE_PATH" >&2
|
|
70
|
+
for warning in "${WARNINGS[@]}"; do
|
|
71
|
+
printf ' WARN: %s\n' "$warning" >&2
|
|
72
|
+
done
|
|
73
|
+
printf '\n' >&2
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
exit 0
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# nextjs profile
|
|
2
|
+
|
|
3
|
+
Reagent profile for Next.js projects using the App Router (Next.js 13+).
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
Install this profile when your project:
|
|
8
|
+
|
|
9
|
+
- Uses Next.js with the App Router (`app/` directory)
|
|
10
|
+
- Has a mix of Server and Client Components
|
|
11
|
+
- Uses `next build` and `next lint` as quality gates
|
|
12
|
+
|
|
13
|
+
## What this profile installs
|
|
14
|
+
|
|
15
|
+
### Hooks
|
|
16
|
+
|
|
17
|
+
- **server-component-drift.sh** — PostToolUse/Write: warns on React client hooks in files missing `'use client'`, `dangerouslySetInnerHTML` usage, and unnecessary `'use client'` in data-fetching-only files.
|
|
18
|
+
|
|
19
|
+
### Quality gates (gates.yaml)
|
|
20
|
+
|
|
21
|
+
| Gate | Command | On failure |
|
|
22
|
+
| ----------------- | ------------------ | ---------- |
|
|
23
|
+
| next-build | `npx next build` | block |
|
|
24
|
+
| next-lint | `npx next lint` | block |
|
|
25
|
+
| nextjs-type-check | `npx tsc --noEmit` | block |
|
|
26
|
+
|
|
27
|
+
### Agents
|
|
28
|
+
|
|
29
|
+
- `nextjs-specialist` — Next.js App Router, RSC, streaming
|
|
30
|
+
- `frontend-specialist` — general frontend patterns
|
|
31
|
+
- `performance-engineer` — Core Web Vitals and bundle optimization
|
|
32
|
+
- `security-engineer-appsec` — XSS, CSRF, and Next.js security headers
|
|
33
|
+
|
|
34
|
+
## Recommended additions
|
|
35
|
+
|
|
36
|
+
- Playwright e2e tests (`npx playwright test`)
|
|
37
|
+
- `@next/bundle-analyzer` for bundle analysis
|
|
38
|
+
- Lighthouse CI for CWV regression
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
reagent init --profile nextjs
|
|
44
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
gates:
|
|
2
|
+
- name: next-build
|
|
3
|
+
command: npx next build
|
|
4
|
+
description: Next.js production build must succeed
|
|
5
|
+
on_failure: block
|
|
6
|
+
|
|
7
|
+
- name: next-lint
|
|
8
|
+
command: npx next lint
|
|
9
|
+
description: Next.js ESLint checks must pass
|
|
10
|
+
on_failure: block
|
|
11
|
+
|
|
12
|
+
- name: nextjs-type-check
|
|
13
|
+
command: npx tsc --noEmit
|
|
14
|
+
description: TypeScript must compile without errors
|
|
15
|
+
on_failure: block
|