diff --git a/.agents/README.md b/.agents/README.md new file mode 100644 index 0000000..b166d1a --- /dev/null +++ b/.agents/README.md @@ -0,0 +1,25 @@ +# .agents/ - Codex Skill Entrypoints + +> Codex loads project-local skills from this directory. These packages are the Codex-facing entrypoints for reusable workflows that need scripts, references, or progressive context loading. + +## Directory Overview + +| Directory | Responsibility | Notes | +|-----------|----------------|-------| +| [skills/](skills/) | Project-local Codex skills | Mirrors the reusable skill packages originally maintained under `.claude/skills/` | + +## Boundary With .codex/ + +| Directory | Purpose | +|-----------|---------| +| `.agents/skills/` | Skills that Codex can discover and invoke from natural-language requests | +| `.codex/agents/` | Codex sub-agent configuration in TOML format | +| `.codex/hooks/` | Hook scripts and Codex hook configuration | +| `.claude/` | Legacy Claude Code prompts, rules, and historical source material | + +## Maintenance + +- Add a `SKILL.md` with frontmatter for every skill package. +- Keep each skill's scripts and references inside the same skill directory. +- Update [skills/README.md](skills/README.md) when adding, removing, or renaming a skill. +- Prefer `.agents/skills//...` paths in Codex-facing docs. diff --git a/.agents/skills/README.md b/.agents/skills/README.md new file mode 100644 index 0000000..8f0dbdb --- /dev/null +++ b/.agents/skills/README.md @@ -0,0 +1,47 @@ +# skills/ - Codex Skill Packages + +> Project-local skills for Codex. Each package contains a `SKILL.md` entrypoint, plus optional `scripts/` and `references/` directories. + +## File Manifest + +| Skill | Purpose | Trigger Scenario | +|-------|---------|------------------| +| [prd-import/](prd-import/) | Convert non-Markdown requirement formats (`.docx`, `.xlsx`, `.pptx`) into markdown source material | Product or backend hands over Word, Excel, or PowerPoint requirements | +| [ext-dep-audit/](ext-dep-audit/) | Dependency security and health audit | Dependency inspection, vulnerability checks, outdated packages | +| [ext-perf-audit/](ext-perf-audit/) | Frontend performance audit | Page jank, bundle size, render performance, initial load optimization | +| [ext-a11y-check/](ext-a11y-check/) | Accessibility WCAG 2.1 AA compliance check | Screen reader, keyboard navigation, semantic HTML, antd accessibility review | +| [ext-changelog/](ext-changelog/) | Human-readable change impact report | Weekly reports, handoffs, retrospectives, recent-change summaries | + +## Naming Conventions + +- `ext-*` means optional analysis/audit skill, used on demand. +- Names without `ext-` are companion skills for the main workflow, such as `prd-import`. + +## Directory Structure + +```text +skills// +|-- SKILL.md +|-- scripts/ +| `-- helper.sh +`-- references/ + `-- checklist.md +``` + +## Script Conventions + +- Scripts should be invoked through paths under `.agents/skills//scripts/`. +- Scripts collect deterministic data; Codex interprets the result. +- Scripts should print useful diagnostics and avoid destructive behavior. + +## References + +- Keep long checklists or format guides in `references/`. +- Link to references from `SKILL.md`; do not inline large reference material in the skill body. + +## Adding A Skill + +1. Create `.agents/skills//SKILL.md`. +2. Add optional `scripts/` and `references/` folders. +3. Register the skill in this README. +4. Update any workflow docs if users need to invoke it directly. diff --git a/.agents/skills/ext-a11y-check/SKILL.md b/.agents/skills/ext-a11y-check/SKILL.md new file mode 100644 index 0000000..d19aa51 --- /dev/null +++ b/.agents/skills/ext-a11y-check/SKILL.md @@ -0,0 +1,53 @@ +--- +name: ext-a11y-check +description: Accessibility audit. Performs WCAG 2.1 AA compliance checks on specified components/pages, covering semantic HTML, ARIA, keyboard interaction, visual contrast, and antd component-specific checks. Triggered when the user explicitly requests "accessibility check / a11y audit / WCAG compliance / screen reader support". +--- + +# ext-a11y-check โ€” Accessibility Compliance Check + +You are now an Accessibility expert. Perform a WCAG 2.1 AA compliance check on the specified component or page. + +## Execution Approach + +A11y checks rely primarily on static analysis (reading JSX / CSS) โ€” there are no definitive scripts. AI scans the source code item-by-item against [references/wcag-aa-checklist.md](references/wcag-aa-checklist.md) and cross-references [references/antd-a11y-notes.md](references/antd-a11y-notes.md) for antd-specific checks. + +## Audit Flow + +1. Read the file/directory specified by `$ARGUMENTS` +2. Check each item across the 5 dimensions in [references/wcag-aa-checklist.md](references/wcag-aa-checklist.md): + - Semantic HTML + - ARIA attributes + - Keyboard interaction + - Visual (contrast / alt text / text scaling) + - antd component-specific checks +3. Link each issue to the specific WCAG 2.1 criterion (e.g. `1.1.1 Non-text Content`) +4. Output violations + improvements + compliance rate + +## Output Format + +``` +๐Ÿ”ด Violations (WCAG AA non-compliant): +- [file:line] Issue description + Standard: WCAG 2.1 criterion number (e.g. 1.1.1 Non-text Content) + Impact: Specific affected group (e.g. visually impaired users cannot determine the button's purpose) + Fix: Code example + +๐ŸŸก Improvements (enhances experience but not required): +- [file:line] Issue description + Fix: Proposed solution + +๐Ÿ“Š Compliance rate: X/Y items passing, Rating: AA / Non-compliant +``` + +## Usage + +``` +/ext-a11y-check workspace/src/features/login/ +/ext-a11y-check workspace/src/components/DataTable.tsx +``` + +## Design Principles + +- Use native HTML semantics where they suffice; don't overuse ARIA +- Every ๐Ÿ”ด violation must cite the WCAG criterion number so users can look it up +- Never auto-modify code โ€” output a list of issues and recommendations only; fixes are done manually by the user or via `/fix` diff --git a/.agents/skills/ext-a11y-check/references/antd-a11y-notes.md b/.agents/skills/ext-a11y-check/references/antd-a11y-notes.md new file mode 100644 index 0000000..916cfb0 --- /dev/null +++ b/.agents/skills/ext-a11y-check/references/antd-a11y-notes.md @@ -0,0 +1,111 @@ +# antd Component Accessibility Notes + +> antd v5 has built-in a11y for most components. The following are easy-to-miss spots and pitfalls when customizing. + +## Table + +```tsx +// Recommended: add summary (screen readers will announce it) +Total: X items} + rowKey="id" +/> +``` + +- `rowKey` must be stable; never use index +- When customizing header render, ensure `th` semantics are preserved +- For complex headers, use the `title` prop on `Table.Column` โ€” don't write raw JSX that breaks the `scope` attribute + +## Modal + +```tsx + +``` + +- `title` is required; don't pass `null` (unless you implement `aria-labelledby` yourself) +- `closable` defaults to true (keep the close button); don't disable it +- `keyboard` defaults to true (Esc to close); don't disable it +- Focus trapping is handled by antd + +## Form + +- `Form.Item`'s `label` is automatically associated by id โ€” leave it as-is +- Error messages have `role="alert"` and will be announced by screen readers +- Custom components wired to `Form.Item` must implement `value` + `onChange`; don't rely solely on internal state + +## Icon Buttons + +```tsx +// โŒ + + +``` + +Replacement list: +- `
` โ†’ ` + + +// โœ… use ARIA only when native semantics are insufficient +
...
// div has no tablist semantics natively +``` + +## 3. Keyboard Interaction + +### 3.1 Interactive elements not reachable via Tab +**Standard**: WCAG 2.1.1 Keyboard + +- All `onClick` elements must be focusable (native button/a/input are by default; divs need `tabIndex={0}`) +- Use `disabled` to disable elements โ€” not `pointer-events: none` (which still allows Tab focus) + +### 3.2 Missing keyboard event handlers +**Standard**: WCAG 2.1.1 + +```tsx +// โŒ responds to mouse only +
...
+ +// โœ… add keyDown +
(e.key === 'Enter' || e.key === ' ') && handle()} + tabIndex={0} + role="button" +>...
+``` + +### 3.3 Modal missing focus trap +**Standard**: WCAG 2.4.3 Focus Order + +- When a modal opens, focus should move into it; when it closes, focus should return to the trigger element +- Tab key should cycle within the modal and not reach background content +- antd Modal already handles this; custom overlays need to implement it + +### 3.4 Missing Esc to close +- Modal / Drawer / Popover should support closing with Esc +- antd supports this by default; custom components need to add it + +## 4. Visual + +### 4.1 Insufficient contrast +**Standard**: WCAG 1.4.3 Contrast (Minimum) + +- Body text: 4.5:1 +- Large text (18pt or 14pt bold): 3:1 +- Non-text elements (icons / borders): 3:1 + +How to check: +- Read color values from CSS / theme.ts +- Compare text color against background color +- Disabled state text is exempt from this rule (WCAG allows an exception), but should still be legible + +### 4.2 Color as the only means of conveying information +**Standard**: WCAG 1.4.1 Use of Color + +```tsx +// โŒ red = error โ€” invisible to color-blind users +Required + +// โœ… color + icon/text + + Required + +``` + +### 4.3 Missing alt text on images +**Standard**: WCAG 1.1.1 Non-text Content + +```tsx +// โŒ + + +// โœ… meaningful image +Zhang San's avatar + +// โœ… decorative image + +``` + +### 4.4 Text overflow at scaled sizes +**Standard**: WCAG 1.4.4 Resize text + +- At 200% browser zoom, there should be no horizontal scrollbar and no text clipping +- Use rem/em instead of fixed px, or use clamp() + +## 5. antd Component-specific Checks + +See [antd-a11y-notes.md](antd-a11y-notes.md) diff --git a/.agents/skills/ext-changelog/SKILL.md b/.agents/skills/ext-changelog/SKILL.md new file mode 100644 index 0000000..f3cf293 --- /dev/null +++ b/.agents/skills/ext-changelog/SKILL.md @@ -0,0 +1,100 @@ +--- +name: ext-changelog +description: Generate a human-readable code change impact report โ€” aggregates commits by module, identifies risk areas, and links to PRDs / tasks / bugs. Used for weekly reports, handoffs, and retrospectives. Unlike /release (structured changelog for version tags). Triggered when the user explicitly requests "change report / weekly report / what changed recently / handoff document". +--- + +# ext-changelog โ€” Change Impact Report + +You are now a code change analyst. Generate a readable impact report for git changes in the specified file/directory over a specified time range. + +## Difference from /release + +- `/release` โ€” oriented toward **publishing**; outputs a structured changelog for tags/releases +- `/ext-changelog` โ€” oriented toward **understanding**; outputs a human-readable change narrative for weekly reports / handoffs / retrospectives + +## Execution Approach + +**Run git log through scripts; AI handles grouping and interpretation** โ€” do not let AI reconstruct commits from memory. + +### Step 1: Get the commit list + +```bash +bash .agents/skills/ext-changelog/scripts/range-commits.sh [since] [scope] [author] +``` + +Parameters (all optional): +- `since` โ€” start date; defaults to `7 days ago`; also accepts `2026-04-01` +- `scope` โ€” path scope; defaults to `.` (entire repo) +- `author` โ€” author filter; defaults to empty (all authors) + +Each output line: `hash|date|author|subject` + +### Step 2: Get changed file statistics + +```bash +bash .agents/skills/ext-changelog/scripts/changed-files.sh [since] [scope] +``` + +Output: A/M/D status for each file + its module directory. + +### Step 3: AI aggregates by module + +After reading the script output: +1. Group by `workspace/src/features//` prefix +2. Parse commit messages in `type(scope): description` format +3. Link to references in `docs/prds/` / `docs/tasks/` / `docs/bug-reports/` +4. Identify risk areas: + - Large-scale changes (a single commit touching > 10 files) + - Cross-module changes (one commit spanning multiple features) + - Commit messages containing `WIP` / `TODO` / `FIXME` + - Feature commits not linked to any PRD or task + +## Output Format + +```markdown +# Change Report: 2026-04-10 โ†’ 2026-04-17 + +## Summary +This week the main work was completing the login module, fixing 3 bugs, and refactoring the auth logic. + +## Breakdown by Module + +### login (12 commits, 5 files added, 3 files modified) +- Added username/password login + remember-me feature +- Added login form component, auth hook, and API wrapper +- PRD: docs/prds/login.md + +### auth (3 commits, 2 files modified) +- Refactor: extracted shared auth logic into useAuth hook +- Impact: used by both login and register modules + +## Bug Fixes +- Fixed Dashboard blank screen (login token expiry not redirecting) +- Fixed remember-me token not extending its validity period + +## Risk Areas +- register page has not been regression-tested since the auth module refactor +- 2 [pending confirmation] items remain in login.md PRD + +## Stats +- Total commits: 18 +- Files added: 7 +- Files modified: 11 +- Active contributors: 2 (alice, bob) +``` + +## Usage + +``` +/ext-changelog # this week's changes +/ext-changelog --since 2026-04-01 # this month's changes +/ext-changelog workspace/src/features/login/ # login module changes +/ext-changelog --author alice --since 2026-04-14 # Alice's output over the last 3 days +``` + +## Design Principles + +- All git commands go through scripts; AI never manually constructs `git log` arguments +- Reports should read as a **narrative**, not a raw dump of the commit list +- Risk areas must be specific (point to a file or module); no filler like "recommend more testing" +- Read-only: never modifies code diff --git a/.agents/skills/ext-changelog/scripts/changed-files.sh b/.agents/skills/ext-changelog/scripts/changed-files.sh new file mode 100644 index 0000000..faad529 --- /dev/null +++ b/.agents/skills/ext-changelog/scripts/changed-files.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# changed-files.sh โ€” list files changed within the specified range (A/M/D) +# usage: bash .agents/skills/ext-changelog/scripts/changed-files.sh [since] [scope] + +set -u + +SINCE="${1:-7 days ago}" +SCOPE="${2:-.}" + +ROOT="$(cd "$(dirname "$0")/../../../.." && pwd)" +cd "$ROOT" || exit 0 + +if [ ! -d ".git" ]; then + echo "โŒ Not a git repository" + exit 0 +fi + +echo "===== Changed file list (since=$SINCE, scope=$SCOPE) =====" +echo "Format: (A=Added, M=Modified, D=Deleted, R=Renamed)" +echo "" + +git log --since="$SINCE" --no-merges --name-status --pretty=format:"" -- "$SCOPE" \ + | grep -E "^[AMDR]" \ + | sort -u + +echo "" +echo "===== Aggregated by module =====" +git log --since="$SINCE" --no-merges --name-status --pretty=format:"" -- "$SCOPE" \ + | grep -E "^[AMDR]" \ + | awk '{print $2}' \ + | awk -F'/' '{ + if ($0 ~ /^workspace\/src\/features\//) print $4 + else if ($0 ~ /^workspace\/src\/pages\//) print "pages/" $4 + else if ($0 ~ /^workspace\/src\/components\//) print "components" + else if ($0 ~ /^workspace\/src\//) print "src/" $3 + else if ($0 ~ /^docs\//) print "docs/" $2 + else print "root" + }' \ + | sort | uniq -c | sort -rn diff --git a/.agents/skills/ext-changelog/scripts/range-commits.sh b/.agents/skills/ext-changelog/scripts/range-commits.sh new file mode 100644 index 0000000..03db827 --- /dev/null +++ b/.agents/skills/ext-changelog/scripts/range-commits.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# range-commits.sh โ€” output the list of commits within the specified range +# usage: bash .agents/skills/ext-changelog/scripts/range-commits.sh [since] [scope] [author] +# e.g.: bash ... "7 days ago" +# bash ... "2026-04-01" +# bash ... "7 days ago" "workspace/src/features/login/" +# bash ... "7 days ago" "." "alice" + +set -u + +SINCE="${1:-7 days ago}" +SCOPE="${2:-.}" +AUTHOR="${3:-}" + +ROOT="$(cd "$(dirname "$0")/../../../.." && pwd)" +cd "$ROOT" || exit 0 + +if [ ! -d ".git" ]; then + echo "โŒ Not a git repository" + exit 0 +fi + +echo "===== Commit list (since=$SINCE, scope=$SCOPE, author=${AUTHOR:-all}) =====" + +GIT_ARGS=(log --since="$SINCE" --no-merges --pretty=format:"%h|%ad|%an|%s" --date=short) +if [ -n "$AUTHOR" ]; then + GIT_ARGS+=(--author="$AUTHOR") +fi +GIT_ARGS+=(-- "$SCOPE") + +git "${GIT_ARGS[@]}" +echo "" # ensure trailing newline +echo "" +echo "===== Stats =====" +TOTAL=$(git "${GIT_ARGS[@]}" | wc -l | tr -d ' ') +echo "Total commits: $TOTAL" +echo "Active authors:" +git "${GIT_ARGS[@]}" | awk -F'|' '{print " " $3}' | sort -u diff --git a/.agents/skills/ext-dep-audit/SKILL.md b/.agents/skills/ext-dep-audit/SKILL.md new file mode 100644 index 0000000..527ddca --- /dev/null +++ b/.agents/skills/ext-dep-audit/SKILL.md @@ -0,0 +1,88 @@ +--- +name: ext-dep-audit +description: Dependency security and health audit. Scans for pnpm vulnerabilities, outdated dependencies, redundant packages, license risks, and Umi built-in dependency conflicts. Triggered when the user explicitly requests "dependency audit / dependency scan / security scan / check outdated packages". +--- + +# ext-dep-audit โ€” Dependency Audit + +You are now a dependency security and health audit expert. Perform a comprehensive checkup on `workspace/package.json`. + +## Execution Approach + +**Run scripts first to get deterministic results, then use AI for interpretation** โ€” do not have AI guess the output of `pnpm audit`. + +### Step 1: Security Vulnerability Scan + +```bash +bash .agents/skills/ext-dep-audit/scripts/pnpm-audit.sh +``` + +The script outputs JSON. Classify by severity when interpreting: + +| Level | Action | +|-------|--------| +| critical / high | Must fix immediately; provide `pnpm update @` | +| moderate | Assess scope of impact; recommend a fix timeline | +| low | Log it; address in the next iteration | + +### Step 2: Umi Built-in Dependency Conflicts + +```bash +bash .agents/skills/ext-dep-audit/scripts/check-umi-conflict.sh +``` + +The script cross-references [references/umi-builtin-deps.md](references/umi-builtin-deps.md); any conflicting dependency is flagged ๐Ÿ”ด. + +### Step 3: Outdated Dependency Check + +```bash +bash .agents/skills/ext-dep-audit/scripts/check-outdated.sh +``` + +Compares current versions against the latest; flags anything **behind by a major version**. + +### Step 4: Dependency Tree Health (AI analysis) + +After the scripts finish, AI reads `workspace/package.json` and additionally checks: + +1. **Deprecated packages** โ€” look for the `deprecated` field +2. **Duplicate functionality** โ€” e.g. moment + dayjs, lodash + ramda, axios + umi-request +3. **Oversized packages** โ€” large packages where only a small part is used (e.g. full `lodash` instead of `lodash/get`) +4. **License risks** โ€” copyleft licenses like GPL / AGPL (important for commercial projects) +5. **Too many direct dependencies** โ€” more than 30 warrants review +6. **devDependencies misplaced in dependencies** โ€” e.g. `@types/*`, `eslint`, `vitest` + +## Output Format + +``` +๐Ÿ”ด Security vulnerabilities (must fix): +- [package@version] Vulnerability description (CVE-xxx) + Fix: pnpm update @ + +๐ŸŸก Health issues (recommended fixes): +- [package] Issue description + Recommendation: Proposed solution + +๐Ÿ”ต Optimization suggestions: +- [package] Suggestion description + +๐Ÿ“Š Summary: + Direct dependencies: X + Security vulnerabilities: X critical / X high / X moderate + Outdated dependencies: X (major version behind) + Redundant dependencies: X + License risks: X +``` + +## Modes + +| Invocation | Behavior | +|-----------|---------| +| `/ext-dep-audit` | Audit only; output report | +| `/ext-dep-audit --fix` | After auditing, **ask the user** whether to apply safe upgrades (patch + minor); major version upgrades are never applied automatically | + +## Design Principles + +- Scripts gather data; AI interprets and recommends โ€” don't let AI guess versions or CVEs from memory +- Every fix recommendation must include a concrete command the user can copy and run +- Destructive operations (major upgrades, deprecated package replacements) are suggested only, never auto-executed diff --git a/.agents/skills/ext-dep-audit/references/umi-builtin-deps.md b/.agents/skills/ext-dep-audit/references/umi-builtin-deps.md new file mode 100644 index 0000000..b509052 --- /dev/null +++ b/.agents/skills/ext-dep-audit/references/umi-builtin-deps.md @@ -0,0 +1,56 @@ +# Umi Built-in Dependency List + +> The following dependencies are provided by `@umijs/max` or the Umi plugin ecosystem and **should not be explicitly installed** in the project. +> Explicit installation causes version mismatches, duplicate bundle entries, and plugins failing to obtain the correct instance. + +## Requests + +| Package | Alternative | +|---------|-------------| +| axios | Use `request` from `@umijs/max` (based on umi-request) | + +## Routing + +| Package | Alternative | +|---------|-------------| +| react-router | Umi's built-in convention-based routing | +| react-router-dom | `history` / `useNavigate` from `@umijs/max` | + +## Build Tools + +| Package | Alternative | +|---------|-------------| +| webpack | Built into Umi (`mfsu` / `chainWebpack` in config.ts) | +| vite | Umi has built-in Vite mode (`vite: {}` in config.ts) | + +## Code Quality + +| Package | Alternative | +|---------|-------------| +| eslint | Use `@umijs/lint` | +| prettier | Use `@umijs/lint` | +| stylelint | Use `@umijs/lint` | + +## UI + +| Package | Alternative | +|---------|-------------| +| antd | Integrated via `@umijs/max`; import normally from `antd` (no explicit install needed) | +| @ant-design/icons | Bundled with antd | + +## State Management + +| Package | Alternative | +|---------|-------------| +| โ€” | Umi includes `@umijs/plugin-model` (useModel); only install Zustand for complex scenarios | + +## Internationalization + +| Package | Alternative | +|---------|-------------| +| react-intl | Use `@umijs/plugin-locale` (a wrapper around react-intl) | + +## How to Verify + +Run `pnpm ls --depth 1 | grep ` to check the actual source of a dependency. +If it is a transitive dependency from `@umijs/max`, you do not need to install it yourself. diff --git a/.agents/skills/ext-dep-audit/scripts/check-outdated.sh b/.agents/skills/ext-dep-audit/scripts/check-outdated.sh new file mode 100644 index 0000000..252b31a --- /dev/null +++ b/.agents/skills/ext-dep-audit/scripts/check-outdated.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# check-outdated.sh โ€” list outdated dependencies +# usage: bash .agents/skills/ext-dep-audit/scripts/check-outdated.sh + +set -u + +ROOT="$(cd "$(dirname "$0")/../../../.." && pwd)" +WORKSPACE="$ROOT/workspace" + +if [ ! -d "$WORKSPACE" ]; then + echo "โŒ workspace/ directory not found" + exit 0 +fi + +cd "$WORKSPACE" || exit 0 + +echo "===== Outdated dependencies =====" +# prefer JSON output; fall back to table on failure +if pnpm outdated --format json 2>/dev/null; then + : +else + echo "โš ๏ธ --format json failed, falling back to table mode:" + pnpm outdated || true +fi + +echo "" +echo "===== Direct dependency count =====" +pnpm ls --depth 0 2>/dev/null | grep -cE "^โ”œ|^โ””" || echo "0" diff --git a/.agents/skills/ext-dep-audit/scripts/check-umi-conflict.sh b/.agents/skills/ext-dep-audit/scripts/check-umi-conflict.sh new file mode 100644 index 0000000..c6dac31 --- /dev/null +++ b/.agents/skills/ext-dep-audit/scripts/check-umi-conflict.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# check-umi-conflict.sh โ€” check whether workspace/package.json installs dependencies already built into Umi +# usage: bash .agents/skills/ext-dep-audit/scripts/check-umi-conflict.sh + +set -u + +ROOT="$(cd "$(dirname "$0")/../../../.." && pwd)" +PKG="$ROOT/workspace/package.json" + +if [ ! -f "$PKG" ]; then + echo "โŒ $PKG not found" + exit 0 +fi + +# List of dependencies built into Umi (keep in sync with references/umi-builtin-deps.md) +UMI_BUILTIN=( + "axios" + "react-router" + "react-router-dom" + "webpack" + "vite" + "eslint" + "prettier" + "stylelint" + "antd" + "@ant-design/icons" +) + +found_any=0 +echo "===== Umi built-in dependency conflict check =====" +for dep in "${UMI_BUILTIN[@]}"; do + if grep -E "\"${dep}\"\\s*:" "$PKG" >/dev/null 2>&1; then + line=$(grep -nE "\"${dep}\"\\s*:" "$PKG" | head -1) + echo "๐Ÿ”ด $dep โ€” already built into Umi; should not be explicitly installed ($line)" + found_any=1 + fi +done + +if [ "$found_any" = "0" ]; then + echo "โœ… No Umi built-in dependency conflicts found" +fi diff --git a/.agents/skills/ext-dep-audit/scripts/pnpm-audit.sh b/.agents/skills/ext-dep-audit/scripts/pnpm-audit.sh new file mode 100644 index 0000000..e96a13b --- /dev/null +++ b/.agents/skills/ext-dep-audit/scripts/pnpm-audit.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# pnpm-audit.sh โ€” run pnpm audit and output JSON for AI parsing +# usage: bash .agents/skills/ext-dep-audit/scripts/pnpm-audit.sh + +set -u + +ROOT="$(cd "$(dirname "$0")/../../../.." && pwd)" +WORKSPACE="$ROOT/workspace" + +if [ ! -d "$WORKSPACE" ]; then + echo "โŒ workspace/ directory not found: $WORKSPACE" + exit 0 +fi + +cd "$WORKSPACE" || exit 0 + +echo "===== pnpm audit (JSON) =====" +if ! pnpm audit --json 2>/dev/null; then + echo "โš ๏ธ --json mode failed, falling back to text mode:" + pnpm audit || true +fi diff --git a/.agents/skills/ext-perf-audit/SKILL.md b/.agents/skills/ext-perf-audit/SKILL.md new file mode 100644 index 0000000..22dcc5e --- /dev/null +++ b/.agents/skills/ext-perf-audit/SKILL.md @@ -0,0 +1,78 @@ +--- +name: ext-perf-audit +description: Frontend performance audit. Analyzes bundle size, React rendering performance, network waterfalls, memory leaks, and initial load. Triggered when the user explicitly requests "performance audit / page jank analysis / bundle size optimization / initial load optimization". +--- + +# ext-perf-audit โ€” Performance Audit + +You are now a frontend performance optimization expert. Perform a performance audit on the specified component / page / module. + +## Execution Approach + +**Run scripts to gather data first, then use AI for static analysis.** Scripts handle measurement; AI handles pattern recognition. + +### Step 1: Build Artifact Analysis (if dist exists) + +```bash +bash .agents/skills/ext-perf-audit/scripts/bundle-size.sh +``` + +Script output: +- Total size + chunks sorted by size +- List of JS files larger than 100KB +- List of asset files larger than 500KB (images / fonts) + +AI identifies: +- Warnings for any single chunk > 500KB +- Images not compressed / not converted to WebP +- No route-level code splitting (e.g., an oversized `index.*.js`) + +### Step 2: Dependency Size Quick Scan + +```bash +bash .agents/skills/ext-perf-audit/scripts/heavy-deps.sh +``` + +The script lists the top 20 largest packages in node_modules. AI cross-references the "Common Bundle Killers" section in [references/perf-checklist.md](references/perf-checklist.md) and provides recommendations. + +### Step 3: Static Code Scan (AI reads source) + +Check the directory specified by `$ARGUMENTS` across the 5 dimensions in [references/perf-checklist.md](references/perf-checklist.md): + +1. **Bundle size** โ€” full-library imports / duplicate dependencies / console.log / missing lazy loading +2. **Rendering performance** โ€” missing memo/useMemo/useCallback / missing keys / new references created in render path / state hoisted too high / JS doing CSS's job +3. **Network performance** โ€” serial requests that could be parallel / missing caching / image formats / missing prefetch +4. **Memory** โ€” useEffect missing cleanup / closures holding large objects / no virtual scrolling +5. **Initial load** โ€” blocking the critical path / missing Skeleton / waterfall requests + +## Output Format + +``` +๐Ÿ”ด Critical (impacts user experience): +- [file:line] Issue description + Impact: Estimated impact (e.g. +800ms on initial load / bundle +400KB) + Fix: Specific solution + code example + +๐ŸŸก Moderate (worth optimizing): +- [file:line] Issue description + Fix: Solution + +๐Ÿ”ต Suggestion (nice to have): +- [file:line] Issue description + +๐Ÿ“Š Overall: X/10, one-sentence summary +``` + +## Usage + +``` +/ext-perf-audit workspace/src/features/login/ +/ext-perf-audit workspace/src/pages/dashboard/ +/ext-perf-audit workspace/src/components/DataTable.tsx +``` + +## Design Principles + +- If a script can measure it, don't ask AI to estimate it (bundle size / dependency size) +- Every recommendation must include an **estimated impact**; suggestions without numbers go under ๐Ÿ”ต only +- Avoid recommending aggressive refactors; prioritize fixes with maximum gain for minimum change diff --git a/.agents/skills/ext-perf-audit/references/perf-checklist.md b/.agents/skills/ext-perf-audit/references/perf-checklist.md new file mode 100644 index 0000000..7f2be6e --- /dev/null +++ b/.agents/skills/ext-perf-audit/references/perf-checklist.md @@ -0,0 +1,151 @@ +# Performance Audit Checklist + +> AI reads source code and checks each item in this list โ€” flag it if it matches. + +## 1. Bundle Size + +### Full-library imports +```typescript +// โŒ import _ from 'lodash' โ†’ bundles the entire lodash (~70KB) +// โœ… import get from 'lodash/get' +// โœ… import { get } from 'lodash-es' (works with tree shaking) +``` + +### Common bundle killers + +| Package | Size | Alternative | +|---------|------|-------------| +| moment | 290KB | dayjs (7KB) | +| lodash (full) | 70KB | lodash-es + tree shake, or individual imports | +| antd (full) | โ€” | Per-component import is handled automatically by @umijs/max; verify import statements use `from 'antd'` | +| @ant-design/icons (full) | 900KB | Single import: `from '@ant-design/icons/lib/icons/PlusOutlined'` | +| echarts (full) | 1MB | `echarts/core` + register on demand | +| crypto-js | 200KB | Use the native WebCrypto API | + +### Duplicate dependencies +- Multiple libraries serving the same purpose: moment + dayjs, axios + umi-request, lodash + ramda +- Run `pnpm ls ` to check for multiple installed versions + +### Missing lazy loading +- Route-level: `dynamic(() => import('./Page'))` +- Large components (Chart / RichEditor / Map) should be lazy-loaded +- Off-screen modals should be lazy-loaded + +### Dev code leaking into production +- `console.log` / `console.debug` +- Dev tools like `why-did-you-render` + +## 2. Rendering Performance + +### Missing memo +```typescript +// โŒ Pure display component re-renders on every parent render +export function UserCard({ user }: Props) { ... } + +// โœ… +export const UserCard = React.memo(function UserCard({ user }: Props) { ... }); +``` + +### Missing key / using index as key +```typescript +// โŒ items.map((item, i) => ) +// โœ… items.map(item => ) +``` + +### New references created in the render path +```typescript +// โŒ Creates a new style object on every render +