mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-01 14:43:28 +08:00
Compare commits
15 Commits
main
...
ecc-tools/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
732751dabf | ||
|
|
a81cffbd59 | ||
|
|
736f1e5b0b | ||
|
|
b71334ea36 | ||
|
|
02442ee94c | ||
|
|
b474d639fc | ||
|
|
823c99d5f2 | ||
|
|
2e0709732d | ||
|
|
32fbbd68a4 | ||
|
|
ef92a3742a | ||
|
|
4749ddc854 | ||
|
|
af761f1fd8 | ||
|
|
86a85b2904 | ||
|
|
f0c418e793 | ||
|
|
f488f59b2a |
@@ -1,442 +1,176 @@
|
||||
---
|
||||
name: everything-claude-code-conventions
|
||||
description: Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.
|
||||
---
|
||||
```markdown
|
||||
# everything-claude-code Development Patterns
|
||||
|
||||
# Everything Claude Code Conventions
|
||||
|
||||
> Generated from [affaan-m/everything-claude-code](https://github.com/affaan-m/everything-claude-code) on 2026-03-20
|
||||
> Auto-generated skill from repository analysis
|
||||
|
||||
## Overview
|
||||
|
||||
This skill teaches Claude the development patterns and conventions used in everything-claude-code.
|
||||
This skill teaches the core development patterns, coding conventions, and collaborative workflows used in the `everything-claude-code` repository. The codebase is written in JavaScript (no framework detected) and is organized for modularity, clarity, and extensibility. It emphasizes clear commit messages, structured documentation, and repeatable workflows for adding new skills, commands, integrations, and conventions.
|
||||
|
||||
## Tech Stack
|
||||
## Coding Conventions
|
||||
|
||||
- **Primary Language**: JavaScript
|
||||
- **Architecture**: hybrid module organization
|
||||
- **Test Location**: separate
|
||||
- **File Naming:**
|
||||
Use `camelCase` for JavaScript files and directories.
|
||||
_Example:_
|
||||
```
|
||||
scripts/lib/installTargets.js
|
||||
tests/hooks/formatCheck.test.js
|
||||
```
|
||||
|
||||
## When to Use This Skill
|
||||
- **Import Style:**
|
||||
Use **relative imports** for modules within the codebase.
|
||||
_Example:_
|
||||
```js
|
||||
const installTarget = require('../../lib/installTargets');
|
||||
```
|
||||
|
||||
Activate this skill when:
|
||||
- Making changes to this repository
|
||||
- Adding new features following established patterns
|
||||
- Writing tests that match project conventions
|
||||
- Creating commits with proper message format
|
||||
- **Export Style:**
|
||||
Both CommonJS (`module.exports`) and ES module (`export`) styles are present.
|
||||
_Example (CommonJS):_
|
||||
```js
|
||||
module.exports = function runHook() { ... };
|
||||
```
|
||||
_Example (ES Module):_
|
||||
```js
|
||||
export function addSkill() { ... }
|
||||
```
|
||||
|
||||
## Commit Conventions
|
||||
- **Commit Messages:**
|
||||
Follow the **Conventional Commits** standard.
|
||||
- Prefixes: `fix`, `feat`, `docs`, `chore`
|
||||
- _Example:_
|
||||
```
|
||||
feat: add install target for VSCode integration
|
||||
fix: correct agent configuration parsing bug
|
||||
```
|
||||
|
||||
Follow these commit message conventions based on 500 analyzed commits.
|
||||
- **Documentation:**
|
||||
Markdown files are used extensively for documenting skills, commands, agents, and conventions.
|
||||
|
||||
### Commit Style: Conventional Commits
|
||||
## Workflows
|
||||
|
||||
### Prefixes Used
|
||||
### Add New Skill or Agent
|
||||
**Trigger:** When introducing a new skill or agent
|
||||
**Command:** `/add-skill`
|
||||
|
||||
- `fix`
|
||||
- `test`
|
||||
- `feat`
|
||||
- `docs`
|
||||
1. Create a new `SKILL.md` file under `skills/<skill-name>/` or `.agents/skills/<agent-name>/`.
|
||||
2. Optionally, add supporting agent definition files (e.g., `agents/<agent-name>.md` or `.codex/agents/<agent-name>.toml`).
|
||||
3. Update or create related documentation/configuration files (e.g., `AGENTS.md`, `.opencode/opencode.json`).
|
||||
|
||||
### Message Guidelines
|
||||
|
||||
- Average message length: ~65 characters
|
||||
- Keep first line concise and descriptive
|
||||
- Use imperative mood ("Add feature" not "Added feature")
|
||||
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
feat(rules): add C# language support
|
||||
_Example:_
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
chore(deps-dev): bump flatted (#675)
|
||||
skills/myNewSkill/SKILL.md
|
||||
.agents/skills/myAgent/SKILL.md
|
||||
agents/myAgent.md
|
||||
.codex/agents/myAgent.toml
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
fix: auto-detect ECC root from plugin cache when CLAUDE_PLUGIN_ROOT is unset (#547) (#691)
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
docs: add Antigravity setup and usage guide (#552)
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
merge: PR #529 — feat(skills): add documentation-lookup, bun-runtime, nextjs-turbopack; feat(agents): add rust-reviewer
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
Revert "Add Kiro IDE support (.kiro/) (#548)"
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
Add Kiro IDE support (.kiro/) (#548)
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
feat: add block-no-verify hook for Claude Code and Cursor (#649)
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### Project Structure: Single Package
|
||||
|
||||
This project uses **hybrid** module organization.
|
||||
|
||||
### Configuration Files
|
||||
|
||||
- `.github/workflows/ci.yml`
|
||||
- `.github/workflows/maintenance.yml`
|
||||
- `.github/workflows/monthly-metrics.yml`
|
||||
- `.github/workflows/release.yml`
|
||||
- `.github/workflows/reusable-release.yml`
|
||||
- `.github/workflows/reusable-test.yml`
|
||||
- `.github/workflows/reusable-validate.yml`
|
||||
- `.opencode/package.json`
|
||||
- `.opencode/tsconfig.json`
|
||||
- `.prettierrc`
|
||||
- `eslint.config.js`
|
||||
- `package.json`
|
||||
|
||||
### Guidelines
|
||||
|
||||
- This project uses a hybrid organization
|
||||
- Follow existing patterns when adding new code
|
||||
|
||||
## Code Style
|
||||
|
||||
### Language: JavaScript
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
| Element | Convention |
|
||||
|---------|------------|
|
||||
| Files | camelCase |
|
||||
| Functions | camelCase |
|
||||
| Classes | PascalCase |
|
||||
| Constants | SCREAMING_SNAKE_CASE |
|
||||
|
||||
### Import Style: Relative Imports
|
||||
|
||||
### Export Style: Mixed Style
|
||||
|
||||
|
||||
*Preferred import style*
|
||||
|
||||
```typescript
|
||||
// Use relative imports
|
||||
import { Button } from '../components/Button'
|
||||
import { useAuth } from './hooks/useAuth'
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Test Framework
|
||||
|
||||
No specific test framework detected — use the repository's existing test patterns.
|
||||
|
||||
### File Pattern: `*.test.js`
|
||||
|
||||
### Test Types
|
||||
|
||||
- **Unit tests**: Test individual functions and components in isolation
|
||||
- **Integration tests**: Test interactions between multiple components/services
|
||||
|
||||
### Coverage
|
||||
|
||||
This project has coverage reporting configured. Aim for 80%+ coverage.
|
||||
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Error Handling Style: Try-Catch Blocks
|
||||
|
||||
|
||||
*Standard error handling pattern*
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const result = await riskyOperation()
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error('Operation failed:', error)
|
||||
throw new Error('User-friendly message')
|
||||
}
|
||||
```
|
||||
|
||||
## Common Workflows
|
||||
|
||||
These workflows were detected from analyzing commit patterns.
|
||||
|
||||
### Database Migration
|
||||
|
||||
Database schema changes with migration files
|
||||
|
||||
**Frequency**: ~2 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Create migration file
|
||||
2. Update schema definitions
|
||||
3. Generate/update types
|
||||
|
||||
**Files typically involved**:
|
||||
- `**/schema.*`
|
||||
- `migrations/*`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
feat: implement --with/--without selective install flags (#679)
|
||||
fix: sync catalog counts with filesystem (27 agents, 113 skills, 58 commands) (#693)
|
||||
feat(rules): add Rust language rules (rebased #660) (#686)
|
||||
```
|
||||
|
||||
### Feature Development
|
||||
|
||||
Standard feature implementation workflow
|
||||
|
||||
**Frequency**: ~22 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Add feature implementation
|
||||
2. Add tests for feature
|
||||
3. Update documentation
|
||||
|
||||
**Files typically involved**:
|
||||
- `manifests/*`
|
||||
- `schemas/*`
|
||||
- `**/*.test.*`
|
||||
- `**/api/**`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
feat(skills): add documentation-lookup, bun-runtime, nextjs-turbopack; feat(agents): add rust-reviewer
|
||||
docs(skills): align documentation-lookup with CONTRIBUTING template; add cross-harness (Codex/Cursor) skill copies
|
||||
fix: address PR review — skill template (When to use, How it works, Examples), bun.lock, next build note, rust-reviewer CI note, doc-lookup privacy/uncertainty
|
||||
```
|
||||
|
||||
### Add Language Rules
|
||||
|
||||
Adds a new programming language to the rules system, including coding style, hooks, patterns, security, and testing guidelines.
|
||||
|
||||
**Frequency**: ~2 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Create a new directory under rules/{language}/
|
||||
2. Add coding-style.md, hooks.md, patterns.md, security.md, and testing.md files with language-specific content
|
||||
3. Optionally reference or link to related skills
|
||||
|
||||
**Files typically involved**:
|
||||
- `rules/*/coding-style.md`
|
||||
- `rules/*/hooks.md`
|
||||
- `rules/*/patterns.md`
|
||||
- `rules/*/security.md`
|
||||
- `rules/*/testing.md`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Create a new directory under rules/{language}/
|
||||
Add coding-style.md, hooks.md, patterns.md, security.md, and testing.md files with language-specific content
|
||||
Optionally reference or link to related skills
|
||||
```
|
||||
|
||||
### Add New Skill
|
||||
|
||||
Adds a new skill to the system, documenting its workflow, triggers, and usage, often with supporting scripts.
|
||||
|
||||
**Frequency**: ~4 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Create a new directory under skills/{skill-name}/
|
||||
2. Add SKILL.md with documentation (When to Use, How It Works, Examples, etc.)
|
||||
3. Optionally add scripts or supporting files under skills/{skill-name}/scripts/
|
||||
4. Address review feedback and iterate on documentation
|
||||
|
||||
**Files typically involved**:
|
||||
- `skills/*/SKILL.md`
|
||||
- `skills/*/scripts/*.sh`
|
||||
- `skills/*/scripts/*.js`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Create a new directory under skills/{skill-name}/
|
||||
Add SKILL.md with documentation (When to Use, How It Works, Examples, etc.)
|
||||
Optionally add scripts or supporting files under skills/{skill-name}/scripts/
|
||||
Address review feedback and iterate on documentation
|
||||
```
|
||||
|
||||
### Add New Agent
|
||||
|
||||
Adds a new agent to the system for code review, build resolution, or other automated tasks.
|
||||
|
||||
**Frequency**: ~2 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Create a new agent markdown file under agents/{agent-name}.md
|
||||
2. Register the agent in AGENTS.md
|
||||
3. Optionally update README.md and docs/COMMAND-AGENT-MAP.md
|
||||
|
||||
**Files typically involved**:
|
||||
- `agents/*.md`
|
||||
- `AGENTS.md`
|
||||
- `README.md`
|
||||
- `docs/COMMAND-AGENT-MAP.md`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Create a new agent markdown file under agents/{agent-name}.md
|
||||
Register the agent in AGENTS.md
|
||||
Optionally update README.md and docs/COMMAND-AGENT-MAP.md
|
||||
```
|
||||
|
||||
### Add New Command
|
||||
|
||||
Adds a new command to the system, often paired with a backing skill.
|
||||
|
||||
**Frequency**: ~1 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Create a new markdown file under commands/{command-name}.md
|
||||
2. Optionally add or update a backing skill under skills/{skill-name}/SKILL.md
|
||||
|
||||
**Files typically involved**:
|
||||
- `commands/*.md`
|
||||
- `skills/*/SKILL.md`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Create a new markdown file under commands/{command-name}.md
|
||||
Optionally add or update a backing skill under skills/{skill-name}/SKILL.md
|
||||
```
|
||||
|
||||
### Sync Catalog Counts
|
||||
|
||||
Synchronizes the documented counts of agents, skills, and commands in AGENTS.md and README.md with the actual repository state.
|
||||
|
||||
**Frequency**: ~3 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Update agent, skill, and command counts in AGENTS.md
|
||||
2. Update the same counts in README.md (quick-start, comparison table, etc.)
|
||||
3. Optionally update other documentation files
|
||||
|
||||
**Files typically involved**:
|
||||
- `AGENTS.md`
|
||||
- `README.md`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Update agent, skill, and command counts in AGENTS.md
|
||||
Update the same counts in README.md (quick-start, comparison table, etc.)
|
||||
Optionally update other documentation files
|
||||
```
|
||||
|
||||
### Add Cross Harness Skill Copies
|
||||
|
||||
Adds skill copies for different agent harnesses (e.g., Codex, Cursor, Antigravity) to ensure compatibility across platforms.
|
||||
|
||||
**Frequency**: ~2 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Copy or adapt SKILL.md to .agents/skills/{skill}/SKILL.md and/or .cursor/skills/{skill}/SKILL.md
|
||||
2. Optionally add harness-specific openai.yaml or config files
|
||||
3. Address review feedback to align with CONTRIBUTING template
|
||||
|
||||
**Files typically involved**:
|
||||
- `.agents/skills/*/SKILL.md`
|
||||
- `.cursor/skills/*/SKILL.md`
|
||||
- `.agents/skills/*/agents/openai.yaml`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Copy or adapt SKILL.md to .agents/skills/{skill}/SKILL.md and/or .cursor/skills/{skill}/SKILL.md
|
||||
Optionally add harness-specific openai.yaml or config files
|
||||
Address review feedback to align with CONTRIBUTING template
|
||||
```
|
||||
|
||||
### Add Or Update Hook
|
||||
|
||||
Adds or updates git or bash hooks to enforce workflow, quality, or security policies.
|
||||
|
||||
**Frequency**: ~1 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Add or update hook scripts in hooks/ or scripts/hooks/
|
||||
2. Register the hook in hooks/hooks.json or similar config
|
||||
3. Optionally add or update tests in tests/hooks/
|
||||
|
||||
**Files typically involved**:
|
||||
- `hooks/*.hook`
|
||||
- `hooks/hooks.json`
|
||||
- `scripts/hooks/*.js`
|
||||
- `tests/hooks/*.test.js`
|
||||
- `.cursor/hooks.json`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Add or update hook scripts in hooks/ or scripts/hooks/
|
||||
Register the hook in hooks/hooks.json or similar config
|
||||
Optionally add or update tests in tests/hooks/
|
||||
```
|
||||
|
||||
### Address Review Feedback
|
||||
|
||||
Addresses code review feedback by updating documentation, scripts, or configuration for clarity, correctness, or convention alignment.
|
||||
|
||||
**Frequency**: ~4 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Edit SKILL.md, agent, or command files to address reviewer comments
|
||||
2. Update examples, headings, or configuration as requested
|
||||
3. Iterate until all review feedback is resolved
|
||||
|
||||
**Files typically involved**:
|
||||
- `skills/*/SKILL.md`
|
||||
- `agents/*.md`
|
||||
- `commands/*.md`
|
||||
- `.agents/skills/*/SKILL.md`
|
||||
- `.cursor/skills/*/SKILL.md`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Edit SKILL.md, agent, or command files to address reviewer comments
|
||||
Update examples, headings, or configuration as requested
|
||||
Iterate until all review feedback is resolved
|
||||
```
|
||||
|
||||
|
||||
## Best Practices
|
||||
|
||||
Based on analysis of the codebase, follow these practices:
|
||||
|
||||
### Do
|
||||
|
||||
- Use conventional commit format (feat:, fix:, etc.)
|
||||
- Follow *.test.js naming pattern
|
||||
- Use camelCase for file names
|
||||
- Prefer mixed exports
|
||||
|
||||
### Don't
|
||||
|
||||
- Don't write vague commit messages
|
||||
- Don't skip tests for new features
|
||||
- Don't deviate from established patterns without discussion
|
||||
|
||||
---
|
||||
|
||||
*This skill was auto-generated by [ECC Tools](https://ecc.tools). Review and customize as needed for your team.*
|
||||
### Add or Update Command
|
||||
**Trigger:** When introducing a new CLI command or workflow
|
||||
**Command:** `/add-command`
|
||||
|
||||
1. Create or update a markdown file in `commands/` (e.g., `commands/myCommand.md`).
|
||||
2. Document usage, purpose, and output in YAML frontmatter and markdown sections.
|
||||
3. Optionally update related documentation or test files.
|
||||
|
||||
_Example:_
|
||||
```
|
||||
commands/reviewFlow.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Add or Update Install Target
|
||||
**Trigger:** When supporting a new IDE, platform, or agent integration
|
||||
**Command:** `/add-install-target`
|
||||
|
||||
1. Add new install scripts and documentation under a tool-specific directory (e.g., `.codebuddy/`, `.gemini/`).
|
||||
2. Update `manifests/install-modules.json` and related schema files.
|
||||
3. Update or add scripts in `scripts/lib/install-targets/<target>.js`.
|
||||
4. Update or add tests for install targets.
|
||||
|
||||
_Example:_
|
||||
```
|
||||
.codebuddy/install.sh
|
||||
manifests/install-modules.json
|
||||
scripts/lib/install-targets/codebuddy.js
|
||||
tests/lib/install-targets.test.js
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Dependency Bump for GitHub Actions
|
||||
**Trigger:** When a new version of a GitHub Actions dependency is released
|
||||
**Command:** `/bump-action`
|
||||
|
||||
1. Update version numbers in `.github/workflows/*.yml` for specific actions.
|
||||
2. Commit with a standardized message indicating the dependency and new version.
|
||||
|
||||
_Example:_
|
||||
```
|
||||
.github/workflows/ci.yml
|
||||
# Update:
|
||||
- uses: actions/checkout@v4
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Fix or Update Hook Scripts
|
||||
**Trigger:** When improving or repairing CLI/editor hooks
|
||||
**Command:** `/fix-hook`
|
||||
|
||||
1. Modify `hooks/hooks.json` to adjust hook configuration or add/remove hooks.
|
||||
2. Update or add scripts in `scripts/hooks/*.js` or `scripts/hooks/*.sh` for hook logic.
|
||||
3. Update or add tests in `tests/hooks/*.test.js`.
|
||||
|
||||
_Example:_
|
||||
```
|
||||
hooks/hooks.json
|
||||
scripts/hooks/formatCheck.js
|
||||
tests/hooks/formatCheck.test.js
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Add or Update ECC Conventions Bundle
|
||||
**Trigger:** When formalizing or updating project conventions and team/process documentation
|
||||
**Command:** `/add-convention`
|
||||
|
||||
1. Add or update markdown or JSON files under `.claude/commands/`, `.claude/rules/`, `.claude/team/`, `.claude/research/`, or `.claude/skills/`.
|
||||
2. Document new or updated conventions, rules, or playbooks.
|
||||
|
||||
_Example:_
|
||||
```
|
||||
.claude/commands/codeReview.md
|
||||
.claude/rules/commitMessage.md
|
||||
.claude/team/members.json
|
||||
.claude/skills/automation/SKILL.md
|
||||
```
|
||||
|
||||
## Testing Patterns
|
||||
|
||||
- **Test Files:**
|
||||
Test files follow the pattern `*.test.js` and are colocated with the code they test or in dedicated `tests/` directories.
|
||||
|
||||
- **Framework:**
|
||||
No specific testing framework detected; use standard Node.js assertions or your preferred test runner.
|
||||
|
||||
_Example:_
|
||||
```
|
||||
tests/lib/install-targets.test.js
|
||||
tests/hooks/formatCheck.test.js
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Purpose |
|
||||
|-------------------|----------------------------------------------------------------|
|
||||
| /add-skill | Add a new skill or agent, including documentation and config |
|
||||
| /add-command | Add or update a CLI command or workflow |
|
||||
| /add-install-target | Add or update an install target for integrations |
|
||||
| /bump-action | Bump GitHub Actions workflow dependencies |
|
||||
| /fix-hook | Fix, refactor, or enhance hook scripts and configuration |
|
||||
| /add-convention | Add or update ECC conventions, rules, or team configs |
|
||||
```
|
||||
|
||||
40
.claude/commands/add-new-skill-or-agent.md
Normal file
40
.claude/commands/add-new-skill-or-agent.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: add-new-skill-or-agent
|
||||
description: Workflow command scaffold for add-new-skill-or-agent in everything-claude-code.
|
||||
allowed_tools: ["Bash", "Read", "Write", "Grep", "Glob"]
|
||||
---
|
||||
|
||||
# /add-new-skill-or-agent
|
||||
|
||||
Use this workflow when working on **add-new-skill-or-agent** in `everything-claude-code`.
|
||||
|
||||
## Goal
|
||||
|
||||
Adds a new skill or agent to the codebase, including documentation and configuration.
|
||||
|
||||
## Common Files
|
||||
|
||||
- `skills/*/SKILL.md`
|
||||
- `.agents/skills/*/SKILL.md`
|
||||
- `agents/*.md`
|
||||
- `.codex/agents/*.toml`
|
||||
- `AGENTS.md`
|
||||
- `.opencode/opencode.json`
|
||||
|
||||
## Suggested Sequence
|
||||
|
||||
1. Understand the current state and failure mode before editing.
|
||||
2. Make the smallest coherent change that satisfies the workflow goal.
|
||||
3. Run the most relevant verification for touched files.
|
||||
4. Summarize what changed and what still needs review.
|
||||
|
||||
## Typical Commit Signals
|
||||
|
||||
- Create a new SKILL.md file under skills/<skill-name>/ or .agents/skills/<agent-name>/
|
||||
- Optionally add supporting agent definition files (e.g., agents/<agent-name>.md or .codex/agents/<agent-name>.toml)
|
||||
- Update or create related documentation or configuration files (e.g., AGENTS.md, opencode.json)
|
||||
|
||||
## Notes
|
||||
|
||||
- Treat this as a scaffold, not a hard-coded script.
|
||||
- Update the command if the workflow evolves materially.
|
||||
35
.claude/commands/add-or-update-command.md
Normal file
35
.claude/commands/add-or-update-command.md
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
name: add-or-update-command
|
||||
description: Workflow command scaffold for add-or-update-command in everything-claude-code.
|
||||
allowed_tools: ["Bash", "Read", "Write", "Grep", "Glob"]
|
||||
---
|
||||
|
||||
# /add-or-update-command
|
||||
|
||||
Use this workflow when working on **add-or-update-command** in `everything-claude-code`.
|
||||
|
||||
## Goal
|
||||
|
||||
Adds or updates a command file, often for new workflows, review flows, or agent orchestration.
|
||||
|
||||
## Common Files
|
||||
|
||||
- `commands/*.md`
|
||||
|
||||
## Suggested Sequence
|
||||
|
||||
1. Understand the current state and failure mode before editing.
|
||||
2. Make the smallest coherent change that satisfies the workflow goal.
|
||||
3. Run the most relevant verification for touched files.
|
||||
4. Summarize what changed and what still needs review.
|
||||
|
||||
## Typical Commit Signals
|
||||
|
||||
- Create or update a markdown file in commands/ (e.g., commands/<command>.md)
|
||||
- Document usage, purpose, and output in YAML frontmatter and markdown sections
|
||||
- Optionally update related documentation or test files
|
||||
|
||||
## Notes
|
||||
|
||||
- Treat this as a scaffold, not a hard-coded script.
|
||||
- Update the command if the workflow evolves materially.
|
||||
@@ -14,10 +14,10 @@ Standard feature implementation workflow
|
||||
|
||||
## Common Files
|
||||
|
||||
- `manifests/*`
|
||||
- `schemas/*`
|
||||
- `.opencode/*`
|
||||
- `.opencode/plugins/*`
|
||||
- `.opencode/plugins/lib/*`
|
||||
- `**/*.test.*`
|
||||
- `**/api/**`
|
||||
|
||||
## Suggested Sequence
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"version": "1.3",
|
||||
"schemaVersion": "1.0",
|
||||
"generatedBy": "ecc-tools",
|
||||
"generatedAt": "2026-03-20T12:07:36.496Z",
|
||||
"generatedAt": "2026-04-01T04:44:14.185Z",
|
||||
"repo": "https://github.com/affaan-m/everything-claude-code",
|
||||
"profiles": {
|
||||
"requested": "full",
|
||||
@@ -148,9 +148,9 @@
|
||||
".claude/research/everything-claude-code-research-playbook.md",
|
||||
".claude/team/everything-claude-code-team-config.json",
|
||||
".claude/enterprise/controls.md",
|
||||
".claude/commands/database-migration.md",
|
||||
".claude/commands/feature-development.md",
|
||||
".claude/commands/add-language-rules.md"
|
||||
".claude/commands/add-new-skill-or-agent.md",
|
||||
".claude/commands/add-or-update-command.md"
|
||||
],
|
||||
"packageFiles": {
|
||||
"runtime-core": [
|
||||
@@ -178,9 +178,9 @@
|
||||
".claude/enterprise/controls.md"
|
||||
],
|
||||
"workflow-pack": [
|
||||
".claude/commands/database-migration.md",
|
||||
".claude/commands/feature-development.md",
|
||||
".claude/commands/add-language-rules.md"
|
||||
".claude/commands/add-new-skill-or-agent.md",
|
||||
".claude/commands/add-or-update-command.md"
|
||||
]
|
||||
},
|
||||
"moduleFiles": {
|
||||
@@ -209,9 +209,9 @@
|
||||
".claude/enterprise/controls.md"
|
||||
],
|
||||
"workflow-pack": [
|
||||
".claude/commands/database-migration.md",
|
||||
".claude/commands/feature-development.md",
|
||||
".claude/commands/add-language-rules.md"
|
||||
".claude/commands/add-new-skill-or-agent.md",
|
||||
".claude/commands/add-or-update-command.md"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
@@ -285,11 +285,6 @@
|
||||
"path": ".claude/enterprise/controls.md",
|
||||
"description": "Enterprise governance scaffold for approvals, audit posture, and escalation."
|
||||
},
|
||||
{
|
||||
"moduleId": "workflow-pack",
|
||||
"path": ".claude/commands/database-migration.md",
|
||||
"description": "Workflow command scaffold for database-migration."
|
||||
},
|
||||
{
|
||||
"moduleId": "workflow-pack",
|
||||
"path": ".claude/commands/feature-development.md",
|
||||
@@ -297,22 +292,27 @@
|
||||
},
|
||||
{
|
||||
"moduleId": "workflow-pack",
|
||||
"path": ".claude/commands/add-language-rules.md",
|
||||
"description": "Workflow command scaffold for add-language-rules."
|
||||
"path": ".claude/commands/add-new-skill-or-agent.md",
|
||||
"description": "Workflow command scaffold for add-new-skill-or-agent."
|
||||
},
|
||||
{
|
||||
"moduleId": "workflow-pack",
|
||||
"path": ".claude/commands/add-or-update-command.md",
|
||||
"description": "Workflow command scaffold for add-or-update-command."
|
||||
}
|
||||
],
|
||||
"workflows": [
|
||||
{
|
||||
"command": "database-migration",
|
||||
"path": ".claude/commands/database-migration.md"
|
||||
},
|
||||
{
|
||||
"command": "feature-development",
|
||||
"path": ".claude/commands/feature-development.md"
|
||||
},
|
||||
{
|
||||
"command": "add-language-rules",
|
||||
"path": ".claude/commands/add-language-rules.md"
|
||||
"command": "add-new-skill-or-agent",
|
||||
"path": ".claude/commands/add-new-skill-or-agent.md"
|
||||
},
|
||||
{
|
||||
"command": "add-or-update-command",
|
||||
"path": ".claude/commands/add-or-update-command.md"
|
||||
}
|
||||
],
|
||||
"adapters": {
|
||||
@@ -320,9 +320,9 @@
|
||||
"skillPath": ".claude/skills/everything-claude-code/SKILL.md",
|
||||
"identityPath": ".claude/identity.json",
|
||||
"commandPaths": [
|
||||
".claude/commands/database-migration.md",
|
||||
".claude/commands/feature-development.md",
|
||||
".claude/commands/add-language-rules.md"
|
||||
".claude/commands/add-new-skill-or-agent.md",
|
||||
".claude/commands/add-or-update-command.md"
|
||||
]
|
||||
},
|
||||
"codex": {
|
||||
|
||||
@@ -10,5 +10,5 @@
|
||||
"javascript"
|
||||
],
|
||||
"suggestedBy": "ecc-tools-repo-analysis",
|
||||
"createdAt": "2026-03-20T12:07:57.119Z"
|
||||
"createdAt": "2026-04-01T04:44:50.680Z"
|
||||
}
|
||||
@@ -18,4 +18,4 @@ Use this when the task is documentation-heavy, source-sensitive, or requires bro
|
||||
|
||||
- Primary language: JavaScript
|
||||
- Framework: Not detected
|
||||
- Workflows detected: 10
|
||||
- Workflows detected: 7
|
||||
@@ -4,7 +4,7 @@ Generated by ECC Tools from repository history. Review before treating it as a h
|
||||
|
||||
## Commit Workflow
|
||||
|
||||
- Prefer `conventional` commit messaging with prefixes such as fix, test, feat, docs.
|
||||
- Prefer `conventional` commit messaging with prefixes such as fix, feat, docs, chore.
|
||||
- Keep new changes aligned with the existing pull-request and review flow already present in the repo.
|
||||
|
||||
## Architecture
|
||||
@@ -24,9 +24,9 @@ Generated by ECC Tools from repository history. Review before treating it as a h
|
||||
|
||||
## Detected Workflows
|
||||
|
||||
- database-migration: Database schema changes with migration files
|
||||
- feature-development: Standard feature implementation workflow
|
||||
- add-language-rules: Adds a new programming language to the rules system, including coding style, hooks, patterns, security, and testing guidelines.
|
||||
- add-new-skill-or-agent: Adds a new skill or agent to the codebase, including documentation and configuration.
|
||||
- add-or-update-command: Adds or updates a command file, often for new workflows, review flows, or agent orchestration.
|
||||
|
||||
## Review Reminder
|
||||
|
||||
|
||||
@@ -1,442 +1,176 @@
|
||||
---
|
||||
name: everything-claude-code-conventions
|
||||
description: Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.
|
||||
---
|
||||
```markdown
|
||||
# everything-claude-code Development Patterns
|
||||
|
||||
# Everything Claude Code Conventions
|
||||
|
||||
> Generated from [affaan-m/everything-claude-code](https://github.com/affaan-m/everything-claude-code) on 2026-03-20
|
||||
> Auto-generated skill from repository analysis
|
||||
|
||||
## Overview
|
||||
|
||||
This skill teaches Claude the development patterns and conventions used in everything-claude-code.
|
||||
This skill teaches the core development patterns, coding conventions, and collaborative workflows used in the `everything-claude-code` repository. The codebase is written in JavaScript (no framework detected) and is organized for modularity, clarity, and extensibility. It emphasizes clear commit messages, structured documentation, and repeatable workflows for adding new skills, commands, integrations, and conventions.
|
||||
|
||||
## Tech Stack
|
||||
## Coding Conventions
|
||||
|
||||
- **Primary Language**: JavaScript
|
||||
- **Architecture**: hybrid module organization
|
||||
- **Test Location**: separate
|
||||
- **File Naming:**
|
||||
Use `camelCase` for JavaScript files and directories.
|
||||
_Example:_
|
||||
```
|
||||
scripts/lib/installTargets.js
|
||||
tests/hooks/formatCheck.test.js
|
||||
```
|
||||
|
||||
## When to Use This Skill
|
||||
- **Import Style:**
|
||||
Use **relative imports** for modules within the codebase.
|
||||
_Example:_
|
||||
```js
|
||||
const installTarget = require('../../lib/installTargets');
|
||||
```
|
||||
|
||||
Activate this skill when:
|
||||
- Making changes to this repository
|
||||
- Adding new features following established patterns
|
||||
- Writing tests that match project conventions
|
||||
- Creating commits with proper message format
|
||||
- **Export Style:**
|
||||
Both CommonJS (`module.exports`) and ES module (`export`) styles are present.
|
||||
_Example (CommonJS):_
|
||||
```js
|
||||
module.exports = function runHook() { ... };
|
||||
```
|
||||
_Example (ES Module):_
|
||||
```js
|
||||
export function addSkill() { ... }
|
||||
```
|
||||
|
||||
## Commit Conventions
|
||||
- **Commit Messages:**
|
||||
Follow the **Conventional Commits** standard.
|
||||
- Prefixes: `fix`, `feat`, `docs`, `chore`
|
||||
- _Example:_
|
||||
```
|
||||
feat: add install target for VSCode integration
|
||||
fix: correct agent configuration parsing bug
|
||||
```
|
||||
|
||||
Follow these commit message conventions based on 500 analyzed commits.
|
||||
- **Documentation:**
|
||||
Markdown files are used extensively for documenting skills, commands, agents, and conventions.
|
||||
|
||||
### Commit Style: Conventional Commits
|
||||
## Workflows
|
||||
|
||||
### Prefixes Used
|
||||
### Add New Skill or Agent
|
||||
**Trigger:** When introducing a new skill or agent
|
||||
**Command:** `/add-skill`
|
||||
|
||||
- `fix`
|
||||
- `test`
|
||||
- `feat`
|
||||
- `docs`
|
||||
1. Create a new `SKILL.md` file under `skills/<skill-name>/` or `.agents/skills/<agent-name>/`.
|
||||
2. Optionally, add supporting agent definition files (e.g., `agents/<agent-name>.md` or `.codex/agents/<agent-name>.toml`).
|
||||
3. Update or create related documentation/configuration files (e.g., `AGENTS.md`, `.opencode/opencode.json`).
|
||||
|
||||
### Message Guidelines
|
||||
|
||||
- Average message length: ~65 characters
|
||||
- Keep first line concise and descriptive
|
||||
- Use imperative mood ("Add feature" not "Added feature")
|
||||
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
feat(rules): add C# language support
|
||||
_Example:_
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
chore(deps-dev): bump flatted (#675)
|
||||
skills/myNewSkill/SKILL.md
|
||||
.agents/skills/myAgent/SKILL.md
|
||||
agents/myAgent.md
|
||||
.codex/agents/myAgent.toml
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
fix: auto-detect ECC root from plugin cache when CLAUDE_PLUGIN_ROOT is unset (#547) (#691)
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
docs: add Antigravity setup and usage guide (#552)
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
merge: PR #529 — feat(skills): add documentation-lookup, bun-runtime, nextjs-turbopack; feat(agents): add rust-reviewer
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
Revert "Add Kiro IDE support (.kiro/) (#548)"
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
Add Kiro IDE support (.kiro/) (#548)
|
||||
```
|
||||
|
||||
*Commit message example*
|
||||
|
||||
```text
|
||||
feat: add block-no-verify hook for Claude Code and Cursor (#649)
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### Project Structure: Single Package
|
||||
|
||||
This project uses **hybrid** module organization.
|
||||
|
||||
### Configuration Files
|
||||
|
||||
- `.github/workflows/ci.yml`
|
||||
- `.github/workflows/maintenance.yml`
|
||||
- `.github/workflows/monthly-metrics.yml`
|
||||
- `.github/workflows/release.yml`
|
||||
- `.github/workflows/reusable-release.yml`
|
||||
- `.github/workflows/reusable-test.yml`
|
||||
- `.github/workflows/reusable-validate.yml`
|
||||
- `.opencode/package.json`
|
||||
- `.opencode/tsconfig.json`
|
||||
- `.prettierrc`
|
||||
- `eslint.config.js`
|
||||
- `package.json`
|
||||
|
||||
### Guidelines
|
||||
|
||||
- This project uses a hybrid organization
|
||||
- Follow existing patterns when adding new code
|
||||
|
||||
## Code Style
|
||||
|
||||
### Language: JavaScript
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
| Element | Convention |
|
||||
|---------|------------|
|
||||
| Files | camelCase |
|
||||
| Functions | camelCase |
|
||||
| Classes | PascalCase |
|
||||
| Constants | SCREAMING_SNAKE_CASE |
|
||||
|
||||
### Import Style: Relative Imports
|
||||
|
||||
### Export Style: Mixed Style
|
||||
|
||||
|
||||
*Preferred import style*
|
||||
|
||||
```typescript
|
||||
// Use relative imports
|
||||
import { Button } from '../components/Button'
|
||||
import { useAuth } from './hooks/useAuth'
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Test Framework
|
||||
|
||||
No specific test framework detected — use the repository's existing test patterns.
|
||||
|
||||
### File Pattern: `*.test.js`
|
||||
|
||||
### Test Types
|
||||
|
||||
- **Unit tests**: Test individual functions and components in isolation
|
||||
- **Integration tests**: Test interactions between multiple components/services
|
||||
|
||||
### Coverage
|
||||
|
||||
This project has coverage reporting configured. Aim for 80%+ coverage.
|
||||
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Error Handling Style: Try-Catch Blocks
|
||||
|
||||
|
||||
*Standard error handling pattern*
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const result = await riskyOperation()
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error('Operation failed:', error)
|
||||
throw new Error('User-friendly message')
|
||||
}
|
||||
```
|
||||
|
||||
## Common Workflows
|
||||
|
||||
These workflows were detected from analyzing commit patterns.
|
||||
|
||||
### Database Migration
|
||||
|
||||
Database schema changes with migration files
|
||||
|
||||
**Frequency**: ~2 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Create migration file
|
||||
2. Update schema definitions
|
||||
3. Generate/update types
|
||||
|
||||
**Files typically involved**:
|
||||
- `**/schema.*`
|
||||
- `migrations/*`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
feat: implement --with/--without selective install flags (#679)
|
||||
fix: sync catalog counts with filesystem (27 agents, 113 skills, 58 commands) (#693)
|
||||
feat(rules): add Rust language rules (rebased #660) (#686)
|
||||
```
|
||||
|
||||
### Feature Development
|
||||
|
||||
Standard feature implementation workflow
|
||||
|
||||
**Frequency**: ~22 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Add feature implementation
|
||||
2. Add tests for feature
|
||||
3. Update documentation
|
||||
|
||||
**Files typically involved**:
|
||||
- `manifests/*`
|
||||
- `schemas/*`
|
||||
- `**/*.test.*`
|
||||
- `**/api/**`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
feat(skills): add documentation-lookup, bun-runtime, nextjs-turbopack; feat(agents): add rust-reviewer
|
||||
docs(skills): align documentation-lookup with CONTRIBUTING template; add cross-harness (Codex/Cursor) skill copies
|
||||
fix: address PR review — skill template (When to use, How it works, Examples), bun.lock, next build note, rust-reviewer CI note, doc-lookup privacy/uncertainty
|
||||
```
|
||||
|
||||
### Add Language Rules
|
||||
|
||||
Adds a new programming language to the rules system, including coding style, hooks, patterns, security, and testing guidelines.
|
||||
|
||||
**Frequency**: ~2 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Create a new directory under rules/{language}/
|
||||
2. Add coding-style.md, hooks.md, patterns.md, security.md, and testing.md files with language-specific content
|
||||
3. Optionally reference or link to related skills
|
||||
|
||||
**Files typically involved**:
|
||||
- `rules/*/coding-style.md`
|
||||
- `rules/*/hooks.md`
|
||||
- `rules/*/patterns.md`
|
||||
- `rules/*/security.md`
|
||||
- `rules/*/testing.md`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Create a new directory under rules/{language}/
|
||||
Add coding-style.md, hooks.md, patterns.md, security.md, and testing.md files with language-specific content
|
||||
Optionally reference or link to related skills
|
||||
```
|
||||
|
||||
### Add New Skill
|
||||
|
||||
Adds a new skill to the system, documenting its workflow, triggers, and usage, often with supporting scripts.
|
||||
|
||||
**Frequency**: ~4 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Create a new directory under skills/{skill-name}/
|
||||
2. Add SKILL.md with documentation (When to Use, How It Works, Examples, etc.)
|
||||
3. Optionally add scripts or supporting files under skills/{skill-name}/scripts/
|
||||
4. Address review feedback and iterate on documentation
|
||||
|
||||
**Files typically involved**:
|
||||
- `skills/*/SKILL.md`
|
||||
- `skills/*/scripts/*.sh`
|
||||
- `skills/*/scripts/*.js`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Create a new directory under skills/{skill-name}/
|
||||
Add SKILL.md with documentation (When to Use, How It Works, Examples, etc.)
|
||||
Optionally add scripts or supporting files under skills/{skill-name}/scripts/
|
||||
Address review feedback and iterate on documentation
|
||||
```
|
||||
|
||||
### Add New Agent
|
||||
|
||||
Adds a new agent to the system for code review, build resolution, or other automated tasks.
|
||||
|
||||
**Frequency**: ~2 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Create a new agent markdown file under agents/{agent-name}.md
|
||||
2. Register the agent in AGENTS.md
|
||||
3. Optionally update README.md and docs/COMMAND-AGENT-MAP.md
|
||||
|
||||
**Files typically involved**:
|
||||
- `agents/*.md`
|
||||
- `AGENTS.md`
|
||||
- `README.md`
|
||||
- `docs/COMMAND-AGENT-MAP.md`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Create a new agent markdown file under agents/{agent-name}.md
|
||||
Register the agent in AGENTS.md
|
||||
Optionally update README.md and docs/COMMAND-AGENT-MAP.md
|
||||
```
|
||||
|
||||
### Add New Command
|
||||
|
||||
Adds a new command to the system, often paired with a backing skill.
|
||||
|
||||
**Frequency**: ~1 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Create a new markdown file under commands/{command-name}.md
|
||||
2. Optionally add or update a backing skill under skills/{skill-name}/SKILL.md
|
||||
|
||||
**Files typically involved**:
|
||||
- `commands/*.md`
|
||||
- `skills/*/SKILL.md`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Create a new markdown file under commands/{command-name}.md
|
||||
Optionally add or update a backing skill under skills/{skill-name}/SKILL.md
|
||||
```
|
||||
|
||||
### Sync Catalog Counts
|
||||
|
||||
Synchronizes the documented counts of agents, skills, and commands in AGENTS.md and README.md with the actual repository state.
|
||||
|
||||
**Frequency**: ~3 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Update agent, skill, and command counts in AGENTS.md
|
||||
2. Update the same counts in README.md (quick-start, comparison table, etc.)
|
||||
3. Optionally update other documentation files
|
||||
|
||||
**Files typically involved**:
|
||||
- `AGENTS.md`
|
||||
- `README.md`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Update agent, skill, and command counts in AGENTS.md
|
||||
Update the same counts in README.md (quick-start, comparison table, etc.)
|
||||
Optionally update other documentation files
|
||||
```
|
||||
|
||||
### Add Cross Harness Skill Copies
|
||||
|
||||
Adds skill copies for different agent harnesses (e.g., Codex, Cursor, Antigravity) to ensure compatibility across platforms.
|
||||
|
||||
**Frequency**: ~2 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Copy or adapt SKILL.md to .agents/skills/{skill}/SKILL.md and/or .cursor/skills/{skill}/SKILL.md
|
||||
2. Optionally add harness-specific openai.yaml or config files
|
||||
3. Address review feedback to align with CONTRIBUTING template
|
||||
|
||||
**Files typically involved**:
|
||||
- `.agents/skills/*/SKILL.md`
|
||||
- `.cursor/skills/*/SKILL.md`
|
||||
- `.agents/skills/*/agents/openai.yaml`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Copy or adapt SKILL.md to .agents/skills/{skill}/SKILL.md and/or .cursor/skills/{skill}/SKILL.md
|
||||
Optionally add harness-specific openai.yaml or config files
|
||||
Address review feedback to align with CONTRIBUTING template
|
||||
```
|
||||
|
||||
### Add Or Update Hook
|
||||
|
||||
Adds or updates git or bash hooks to enforce workflow, quality, or security policies.
|
||||
|
||||
**Frequency**: ~1 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Add or update hook scripts in hooks/ or scripts/hooks/
|
||||
2. Register the hook in hooks/hooks.json or similar config
|
||||
3. Optionally add or update tests in tests/hooks/
|
||||
|
||||
**Files typically involved**:
|
||||
- `hooks/*.hook`
|
||||
- `hooks/hooks.json`
|
||||
- `scripts/hooks/*.js`
|
||||
- `tests/hooks/*.test.js`
|
||||
- `.cursor/hooks.json`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Add or update hook scripts in hooks/ or scripts/hooks/
|
||||
Register the hook in hooks/hooks.json or similar config
|
||||
Optionally add or update tests in tests/hooks/
|
||||
```
|
||||
|
||||
### Address Review Feedback
|
||||
|
||||
Addresses code review feedback by updating documentation, scripts, or configuration for clarity, correctness, or convention alignment.
|
||||
|
||||
**Frequency**: ~4 times per month
|
||||
|
||||
**Steps**:
|
||||
1. Edit SKILL.md, agent, or command files to address reviewer comments
|
||||
2. Update examples, headings, or configuration as requested
|
||||
3. Iterate until all review feedback is resolved
|
||||
|
||||
**Files typically involved**:
|
||||
- `skills/*/SKILL.md`
|
||||
- `agents/*.md`
|
||||
- `commands/*.md`
|
||||
- `.agents/skills/*/SKILL.md`
|
||||
- `.cursor/skills/*/SKILL.md`
|
||||
|
||||
**Example commit sequence**:
|
||||
```
|
||||
Edit SKILL.md, agent, or command files to address reviewer comments
|
||||
Update examples, headings, or configuration as requested
|
||||
Iterate until all review feedback is resolved
|
||||
```
|
||||
|
||||
|
||||
## Best Practices
|
||||
|
||||
Based on analysis of the codebase, follow these practices:
|
||||
|
||||
### Do
|
||||
|
||||
- Use conventional commit format (feat:, fix:, etc.)
|
||||
- Follow *.test.js naming pattern
|
||||
- Use camelCase for file names
|
||||
- Prefer mixed exports
|
||||
|
||||
### Don't
|
||||
|
||||
- Don't write vague commit messages
|
||||
- Don't skip tests for new features
|
||||
- Don't deviate from established patterns without discussion
|
||||
|
||||
---
|
||||
|
||||
*This skill was auto-generated by [ECC Tools](https://ecc.tools). Review and customize as needed for your team.*
|
||||
### Add or Update Command
|
||||
**Trigger:** When introducing a new CLI command or workflow
|
||||
**Command:** `/add-command`
|
||||
|
||||
1. Create or update a markdown file in `commands/` (e.g., `commands/myCommand.md`).
|
||||
2. Document usage, purpose, and output in YAML frontmatter and markdown sections.
|
||||
3. Optionally update related documentation or test files.
|
||||
|
||||
_Example:_
|
||||
```
|
||||
commands/reviewFlow.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Add or Update Install Target
|
||||
**Trigger:** When supporting a new IDE, platform, or agent integration
|
||||
**Command:** `/add-install-target`
|
||||
|
||||
1. Add new install scripts and documentation under a tool-specific directory (e.g., `.codebuddy/`, `.gemini/`).
|
||||
2. Update `manifests/install-modules.json` and related schema files.
|
||||
3. Update or add scripts in `scripts/lib/install-targets/<target>.js`.
|
||||
4. Update or add tests for install targets.
|
||||
|
||||
_Example:_
|
||||
```
|
||||
.codebuddy/install.sh
|
||||
manifests/install-modules.json
|
||||
scripts/lib/install-targets/codebuddy.js
|
||||
tests/lib/install-targets.test.js
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Dependency Bump for GitHub Actions
|
||||
**Trigger:** When a new version of a GitHub Actions dependency is released
|
||||
**Command:** `/bump-action`
|
||||
|
||||
1. Update version numbers in `.github/workflows/*.yml` for specific actions.
|
||||
2. Commit with a standardized message indicating the dependency and new version.
|
||||
|
||||
_Example:_
|
||||
```
|
||||
.github/workflows/ci.yml
|
||||
# Update:
|
||||
- uses: actions/checkout@v4
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Fix or Update Hook Scripts
|
||||
**Trigger:** When improving or repairing CLI/editor hooks
|
||||
**Command:** `/fix-hook`
|
||||
|
||||
1. Modify `hooks/hooks.json` to adjust hook configuration or add/remove hooks.
|
||||
2. Update or add scripts in `scripts/hooks/*.js` or `scripts/hooks/*.sh` for hook logic.
|
||||
3. Update or add tests in `tests/hooks/*.test.js`.
|
||||
|
||||
_Example:_
|
||||
```
|
||||
hooks/hooks.json
|
||||
scripts/hooks/formatCheck.js
|
||||
tests/hooks/formatCheck.test.js
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Add or Update ECC Conventions Bundle
|
||||
**Trigger:** When formalizing or updating project conventions and team/process documentation
|
||||
**Command:** `/add-convention`
|
||||
|
||||
1. Add or update markdown or JSON files under `.claude/commands/`, `.claude/rules/`, `.claude/team/`, `.claude/research/`, or `.claude/skills/`.
|
||||
2. Document new or updated conventions, rules, or playbooks.
|
||||
|
||||
_Example:_
|
||||
```
|
||||
.claude/commands/codeReview.md
|
||||
.claude/rules/commitMessage.md
|
||||
.claude/team/members.json
|
||||
.claude/skills/automation/SKILL.md
|
||||
```
|
||||
|
||||
## Testing Patterns
|
||||
|
||||
- **Test Files:**
|
||||
Test files follow the pattern `*.test.js` and are colocated with the code they test or in dedicated `tests/` directories.
|
||||
|
||||
- **Framework:**
|
||||
No specific testing framework detected; use standard Node.js assertions or your preferred test runner.
|
||||
|
||||
_Example:_
|
||||
```
|
||||
tests/lib/install-targets.test.js
|
||||
tests/hooks/formatCheck.test.js
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Purpose |
|
||||
|-------------------|----------------------------------------------------------------|
|
||||
| /add-skill | Add a new skill or agent, including documentation and config |
|
||||
| /add-command | Add or update a CLI command or workflow |
|
||||
| /add-install-target | Add or update an install target for integrations |
|
||||
| /bump-action | Bump GitHub Actions workflow dependencies |
|
||||
| /fix-hook | Fix, refactor, or enhance hook scripts and configuration |
|
||||
| /add-convention | Add or update ECC conventions, rules, or team configs |
|
||||
```
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
".agents/skills/everything-claude-code/SKILL.md"
|
||||
],
|
||||
"commandFiles": [
|
||||
".claude/commands/database-migration.md",
|
||||
".claude/commands/feature-development.md",
|
||||
".claude/commands/add-language-rules.md"
|
||||
".claude/commands/add-new-skill-or-agent.md",
|
||||
".claude/commands/add-or-update-command.md"
|
||||
],
|
||||
"updatedAt": "2026-03-20T12:07:36.496Z"
|
||||
"updatedAt": "2026-04-01T04:44:14.185Z"
|
||||
}
|
||||
4
.github/workflows/reusable-release.yml
vendored
4
.github/workflows/reusable-release.yml
vendored
@@ -28,10 +28,8 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Validate version tag
|
||||
env:
|
||||
INPUT_TAG: ${{ inputs.tag }}
|
||||
run: |
|
||||
if ! [[ "$INPUT_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
if ! [[ "${{ inputs.tag }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "Invalid version tag format. Expected vX.Y.Z"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -1221,9 +1221,9 @@ ECC is the **first plugin to maximize every major AI coding tool**. Here's how e
|
||||
|
||||
| Feature | Claude Code | Cursor IDE | Codex CLI | OpenCode |
|
||||
|---------|------------|------------|-----------|----------|
|
||||
| **Agents** | 36 | Shared (AGENTS.md) | Shared (AGENTS.md) | 12 |
|
||||
| **Commands** | 68 | Shared | Instruction-based | 31 |
|
||||
| **Skills** | 142 | Shared | 10 (native format) | 37 |
|
||||
| **Agents** | 21 | Shared (AGENTS.md) | Shared (AGENTS.md) | 12 |
|
||||
| **Commands** | 52 | Shared | Instruction-based | 31 |
|
||||
| **Skills** | 102 | Shared | 10 (native format) | 37 |
|
||||
| **Hook Events** | 8 types | 15 types | None yet | 11 types |
|
||||
| **Hook Scripts** | 20+ scripts | 16 scripts (DRY adapter) | N/A | Plugin hooks |
|
||||
| **Rules** | 34 (common + lang) | 34 (YAML frontmatter) | Instruction-based | 13 instructions |
|
||||
|
||||
@@ -106,7 +106,7 @@ cp -r everything-claude-code/rules/perl ~/.claude/rules/
|
||||
/plugin list everything-claude-code@everything-claude-code
|
||||
```
|
||||
|
||||
**完成!** 你现在可以使用 36 个代理、142 个技能和 68 个命令。
|
||||
**完成!** 你现在可以使用 13 个代理、43 个技能和 31 个命令。
|
||||
|
||||
### multi-* 命令需要额外配置
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ Public ECC plugin repo for agents, skills, commands, hooks, rules, install surfa
|
||||
- Native-support candidates to fully diff-audit next:
|
||||
- `#1055` Dart / Flutter support
|
||||
- `#1043` C# reviewer and .NET skills
|
||||
- `#834` localized catalog sync and antigravity target filtering
|
||||
- Port or rebuild inside ECC after full audit:
|
||||
- `#894` Jira integration
|
||||
- `#844` ui-demo skill
|
||||
@@ -74,7 +75,3 @@ Keep this file detailed for only the current sprint, blockers, and next actions.
|
||||
- 2026-04-01: Notification PRs `#808` and `#814` were identified as overlapping and should be rebuilt as one unified feature instead of landing as parallel branches.
|
||||
- 2026-04-01: External-source skill PRs `#640`, `#851`, and `#852` were closed under the new ingestion policy; copy ideas from audited source later rather than merging branded/source-import PRs directly.
|
||||
- 2026-04-01: The remaining low GitHub advisory on `ecc2/Cargo.lock` was addressed by moving `ratatui` to `0.30` with `crossterm_0_28`, which updated transitive `lru` from `0.12.5` to `0.16.3`. `cargo build --manifest-path ecc2/Cargo.toml` still passes.
|
||||
- 2026-04-01: Safe core of `#834` was ported directly into `main` instead of merging the PR wholesale. This included stricter install-plan validation, antigravity target filtering that skips unsupported module trees, tracked catalog sync for English plus zh-CN docs, and a dedicated `catalog:sync` write mode.
|
||||
- 2026-04-01: Repo catalog truth is now synced at `36` agents, `68` commands, and `142` skills across the tracked English and zh-CN docs.
|
||||
- 2026-04-01: Legacy emoji and non-essential symbol usage in docs, scripts, and tests was normalized to keep the unicode-safety lane green without weakening the check itself.
|
||||
- 2026-04-01: The remaining self-contained piece of `#834`, `docs/zh-CN/skills/browser-qa/SKILL.md`, was ported directly into the repo. After commit, `#834` should be closed as superseded-by-direct-port.
|
||||
|
||||
@@ -98,21 +98,21 @@ Write to `gan-harness/generator-state.md` after each iteration:
|
||||
|
||||
The Evaluator will specifically penalize these patterns. **Avoid them:**
|
||||
|
||||
- Avoid generic gradient backgrounds (#667eea -> #764ba2 is an instant tell)
|
||||
- Avoid excessive rounded corners on everything
|
||||
- Avoid stock hero sections with "Welcome to [App Name]"
|
||||
- Avoid default Material UI / Shadcn themes without customization
|
||||
- Avoid placeholder images from unsplash/placeholder services
|
||||
- Avoid generic card grids with identical layouts
|
||||
- Avoid "AI-generated" decorative SVG patterns
|
||||
- ❌ Generic gradient backgrounds (#667eea → #764ba2 is an instant tell)
|
||||
- ❌ Excessive rounded corners on everything
|
||||
- ❌ Stock hero sections with "Welcome to [App Name]"
|
||||
- ❌ Default Material UI / Shadcn themes without customization
|
||||
- ❌ Placeholder images from unsplash/placeholder services
|
||||
- ❌ Generic card grids with identical layouts
|
||||
- ❌ "AI-generated" decorative SVG patterns
|
||||
|
||||
**Instead, aim for:**
|
||||
- Use a specific, opinionated color palette (follow the spec)
|
||||
- Use thoughtful typography hierarchy (different weights, sizes for different content)
|
||||
- Use custom layouts that match the content (not generic grids)
|
||||
- Use meaningful animations tied to user actions (not decoration)
|
||||
- Use real empty states with personality
|
||||
- Use error states that help the user (not just "Something went wrong")
|
||||
- ✅ A specific, opinionated color palette (follow the spec)
|
||||
- ✅ Thoughtful typography hierarchy (different weights, sizes for different content)
|
||||
- ✅ Custom layouts that match the content (not generic grids)
|
||||
- ✅ Meaningful animations tied to user actions (not decoration)
|
||||
- ✅ Real empty states with personality
|
||||
- ✅ Error states that help the user (not just "Something went wrong")
|
||||
|
||||
## Interaction with Evaluator
|
||||
|
||||
|
||||
@@ -219,10 +219,10 @@ Create review artifact at `.claude/PRPs/reviews/pr-<NUMBER>-review.md`:
|
||||
|
||||
| Check | Result |
|
||||
|---|---|
|
||||
| Type check | Pass / Fail / Skipped |
|
||||
| Lint | Pass / Fail / Skipped |
|
||||
| Tests | Pass / Fail / Skipped |
|
||||
| Build | Pass / Fail / Skipped |
|
||||
| Type check | ✅ Pass / ❌ Fail / ⏭️ Skipped |
|
||||
| Lint | ✅ / ❌ / ⏭️ |
|
||||
| Tests | ✅ / ❌ / ⏭️ |
|
||||
| Build | ✅ / ❌ / ⏭️ |
|
||||
|
||||
## Files Reviewed
|
||||
<list of files with change type: Added/Modified/Deleted>
|
||||
|
||||
@@ -115,7 +115,7 @@ For each task in **Step-by-Step Tasks**:
|
||||
```
|
||||
If type-check fails → fix the error before moving to the next file.
|
||||
|
||||
4. **Track progress** — Log: `[done] Task N: [task name] — complete`
|
||||
4. **Track progress** — Log: `✅ Task N: [task name] — complete`
|
||||
|
||||
### Handling Deviations
|
||||
|
||||
@@ -234,18 +234,18 @@ Write report to `.claude/PRPs/reports/{plan-name}-report.md`:
|
||||
|
||||
| # | Task | Status | Notes |
|
||||
|---|---|---|---|
|
||||
| 1 | [task name] | [done] Complete | |
|
||||
| 2 | [task name] | [done] Complete | Deviated — [reason] |
|
||||
| 1 | [task name] | ✅ Complete | |
|
||||
| 2 | [task name] | ✅ Complete | Deviated — [reason] |
|
||||
|
||||
## Validation Results
|
||||
|
||||
| Level | Status | Notes |
|
||||
|---|---|---|
|
||||
| Static Analysis | [done] Pass | |
|
||||
| Unit Tests | [done] Pass | N tests written |
|
||||
| Build | [done] Pass | |
|
||||
| Integration | [done] Pass | or N/A |
|
||||
| Edge Cases | [done] Pass | |
|
||||
| Static Analysis | ✅ Pass | |
|
||||
| Unit Tests | ✅ Pass | N tests written |
|
||||
| Build | ✅ Pass | |
|
||||
| Integration | ✅ Pass | or N/A |
|
||||
| Edge Cases | ✅ Pass | |
|
||||
|
||||
## Files Changed
|
||||
|
||||
@@ -297,17 +297,17 @@ Report to user:
|
||||
|
||||
- **Plan**: [plan file path] → archived to completed/
|
||||
- **Branch**: [current branch name]
|
||||
- **Status**: [done] All tasks complete
|
||||
- **Status**: ✅ All tasks complete
|
||||
|
||||
### Validation Summary
|
||||
|
||||
| Check | Status |
|
||||
|---|---|
|
||||
| Type Check | [done] |
|
||||
| Lint | [done] |
|
||||
| Tests | [done] (N written) |
|
||||
| Build | [done] |
|
||||
| Integration | [done] or N/A |
|
||||
| Type Check | ✅ |
|
||||
| Lint | ✅ |
|
||||
| Tests | ✅ (N written) |
|
||||
| Build | ✅ |
|
||||
| Integration | ✅ or N/A |
|
||||
|
||||
### Files Changed
|
||||
- [N] files created, [M] files updated
|
||||
@@ -322,8 +322,8 @@ Report to user:
|
||||
### PRD Progress (if applicable)
|
||||
| Phase | Status |
|
||||
|---|---|
|
||||
| Phase 1 | [done] Complete |
|
||||
| Phase 2 | [next] |
|
||||
| Phase 1 | ✅ Complete |
|
||||
| Phase 2 | ⏳ Next |
|
||||
| ... | ... |
|
||||
|
||||
> Next step: Run `/prp-pr` to create a pull request, or `/code-review` to review changes first.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Everything Claude Code (ECC) — 智能体指令
|
||||
|
||||
这是一个**生产就绪的 AI 编码插件**,提供 36 个专业代理、142 项技能、68 条命令以及自动化钩子工作流,用于软件开发。
|
||||
这是一个**生产就绪的 AI 编码插件**,提供 28 个专业代理、116 项技能、59 条命令以及自动化钩子工作流,用于软件开发。
|
||||
|
||||
**版本:** 1.9.0
|
||||
|
||||
@@ -146,9 +146,9 @@
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
agents/ — 36 个专业子代理
|
||||
skills/ — 142 个工作流技能和领域知识
|
||||
commands/ — 68 个斜杠命令
|
||||
agents/ — 28 个专业子代理
|
||||
skills/ — 115 个工作流技能和领域知识
|
||||
commands/ — 59 个斜杠命令
|
||||
hooks/ — 基于触发的自动化
|
||||
rules/ — 始终遵循的指导方针(通用 + 每种语言)
|
||||
scripts/ — 跨平台 Node.js 实用工具
|
||||
|
||||
@@ -209,7 +209,7 @@ npx ecc-install typescript
|
||||
/plugin list everything-claude-code@everything-claude-code
|
||||
```
|
||||
|
||||
**搞定!** 你现在可以使用 36 个智能体、142 项技能和 68 个命令了。
|
||||
**搞定!** 你现在可以使用 28 个智能体、116 项技能和 59 个命令了。
|
||||
|
||||
***
|
||||
|
||||
@@ -1094,9 +1094,9 @@ opencode
|
||||
|
||||
| 功能特性 | Claude Code | OpenCode | 状态 |
|
||||
|---------|-------------|----------|--------|
|
||||
| 智能体 | PASS: 36 个 | PASS: 12 个 | **Claude Code 领先** |
|
||||
| 命令 | PASS: 68 个 | PASS: 31 个 | **Claude Code 领先** |
|
||||
| 技能 | PASS: 142 项 | PASS: 37 项 | **Claude Code 领先** |
|
||||
| 智能体 | PASS: 28 个 | PASS: 12 个 | **Claude Code 领先** |
|
||||
| 命令 | PASS: 59 个 | PASS: 31 个 | **Claude Code 领先** |
|
||||
| 技能 | PASS: 116 项 | PASS: 37 项 | **Claude Code 领先** |
|
||||
| 钩子 | PASS: 8 种事件类型 | PASS: 11 种事件 | **OpenCode 更多!** |
|
||||
| 规则 | PASS: 29 条 | PASS: 13 条指令 | **Claude Code 领先** |
|
||||
| MCP 服务器 | PASS: 14 个 | PASS: 完整 | **完全对等** |
|
||||
@@ -1206,9 +1206,9 @@ ECC 是**第一个最大化利用每个主要 AI 编码工具的插件**。以
|
||||
|
||||
| 功能特性 | Claude Code | Cursor IDE | Codex CLI | OpenCode |
|
||||
|---------|------------|------------|-----------|----------|
|
||||
| **智能体** | 36 | 共享 (AGENTS.md) | 共享 (AGENTS.md) | 12 |
|
||||
| **命令** | 68 | 共享 | 基于指令 | 31 |
|
||||
| **技能** | 142 | 共享 | 10 (原生格式) | 37 |
|
||||
| **智能体** | 21 | 共享 (AGENTS.md) | 共享 (AGENTS.md) | 12 |
|
||||
| **命令** | 52 | 共享 | 基于指令 | 31 |
|
||||
| **技能** | 102 | 共享 | 10 (原生格式) | 37 |
|
||||
| **钩子事件** | 8 种类型 | 15 种类型 | 暂无 | 11 种类型 |
|
||||
| **钩子脚本** | 20+ 个脚本 | 16 个脚本 (DRY 适配器) | N/A | 插件钩子 |
|
||||
| **规则** | 34 (通用 + 语言) | 34 (YAML 前页) | 基于指令 | 13 条指令 |
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
# Browser QA — 自动化视觉测试与交互验证
|
||||
|
||||
## When to use
|
||||
|
||||
- 功能部署到 staging / preview 之后
|
||||
- 需要验证跨页面的 UI 行为时
|
||||
- 发布前确认布局、表单和交互是否真的可用
|
||||
- 审查涉及前端改动的 PR 时
|
||||
- 做可访问性审计和响应式测试时
|
||||
|
||||
## How it works
|
||||
|
||||
使用浏览器自动化 MCP(claude-in-chrome、Playwright 或 Puppeteer),像真实用户一样与线上页面交互。
|
||||
|
||||
### 阶段 1:冒烟测试
|
||||
```
|
||||
1. 打开目标 URL
|
||||
2. 检查控制台错误(过滤噪声:分析脚本、第三方库)
|
||||
3. 验证网络请求中没有 4xx / 5xx
|
||||
4. 在桌面和移动端视口截图首屏内容
|
||||
5. 检查 Core Web Vitals:LCP < 2.5s,CLS < 0.1,INP < 200ms
|
||||
```
|
||||
|
||||
### 阶段 2:交互测试
|
||||
```
|
||||
1. 点击所有导航链接,验证没有死链
|
||||
2. 使用有效数据提交表单,验证成功态
|
||||
3. 使用无效数据提交表单,验证错误态
|
||||
4. 测试认证流程:登录 → 受保护页面 → 登出
|
||||
5. 测试关键用户路径(结账、引导、搜索)
|
||||
```
|
||||
|
||||
### 阶段 3:视觉回归
|
||||
```
|
||||
1. 在 3 个断点(375px、768px、1440px)对关键页面截图
|
||||
2. 与基线截图对比(如果已保存)
|
||||
3. 标记 > 5px 的布局偏移、缺失元素、内容溢出
|
||||
4. 如适用,检查暗色模式
|
||||
```
|
||||
|
||||
### 阶段 4:可访问性
|
||||
```
|
||||
1. 在每个页面运行 axe-core 或等价工具
|
||||
2. 标记 WCAG AA 违规(对比度、标签、焦点顺序)
|
||||
3. 验证键盘导航可以端到端工作
|
||||
4. 检查屏幕阅读器地标
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
```markdown
|
||||
## QA 报告 — [URL] — [timestamp]
|
||||
|
||||
### 冒烟测试
|
||||
- 控制台错误:0 个严重错误,2 个警告(分析脚本噪声)
|
||||
- 网络:全部 200/304,无失败请求
|
||||
- Core Web Vitals:LCP 1.2s,CLS 0.02,INP 89ms
|
||||
|
||||
### 交互
|
||||
- [done] 导航链接:12/12 正常
|
||||
- [issue] 联系表单:无效邮箱缺少错误态
|
||||
- [done] 认证流程:登录 / 登出正常
|
||||
|
||||
### 视觉
|
||||
- [issue] Hero 区域在 375px 视口下溢出
|
||||
- [done] 暗色模式:所有页面一致
|
||||
|
||||
### 可访问性
|
||||
- 2 个 AA 级违规:Hero 图片缺少 alt 文本,页脚链接对比度过低
|
||||
|
||||
### 结论:修复后可发布(2 个问题,0 个阻塞项)
|
||||
```
|
||||
|
||||
## 集成
|
||||
|
||||
可与任意浏览器 MCP 配合:
|
||||
- `mChild__claude-in-chrome__*` 工具(推荐,直接使用你的真实 Chrome)
|
||||
- 通过 `mcp__browserbase__*` 使用 Playwright
|
||||
- 直接运行 Puppeteer 脚本
|
||||
|
||||
可与 `/canary-watch` 搭配用于发布后的持续监控。
|
||||
@@ -102,15 +102,13 @@
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "echo '\\n ecc-universal installed!\\n Run: npx ecc typescript\\n Compat: npx ecc-install typescript\\n Docs: https://github.com/affaan-m/everything-claude-code\\n'",
|
||||
"catalog:check": "node scripts/ci/catalog.js --text",
|
||||
"catalog:sync": "node scripts/ci/catalog.js --write --text",
|
||||
"lint": "eslint . && markdownlint '**/*.md' --ignore node_modules",
|
||||
"harness:audit": "node scripts/harness-audit.js",
|
||||
"claw": "node scripts/claw.js",
|
||||
"orchestrate:status": "node scripts/orchestration-status.js",
|
||||
"orchestrate:worker": "bash scripts/orchestrate-codex-worker.sh",
|
||||
"orchestrate:tmux": "node scripts/orchestrate-worktrees.js",
|
||||
"test": "node scripts/ci/check-unicode-safety.js && node scripts/ci/validate-agents.js && node scripts/ci/validate-commands.js && node scripts/ci/validate-rules.js && node scripts/ci/validate-skills.js && node scripts/ci/validate-hooks.js && node scripts/ci/validate-install-manifests.js && node scripts/ci/validate-no-personal-paths.js && npm run catalog:check && node tests/run-all.js",
|
||||
"test": "node scripts/ci/check-unicode-safety.js && node scripts/ci/validate-agents.js && node scripts/ci/validate-commands.js && node scripts/ci/validate-rules.js && node scripts/ci/validate-skills.js && node scripts/ci/validate-hooks.js && node scripts/ci/validate-install-manifests.js && node scripts/ci/validate-no-personal-paths.js && node scripts/ci/catalog.js --text && node tests/run-all.js",
|
||||
"coverage": "c8 --all --include=\"scripts/**/*.js\" --check-coverage --lines 80 --functions 80 --branches 80 --statements 80 --reporter=text --reporter=lcov node tests/run-all.js"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Verify repo catalog counts against tracked documentation files.
|
||||
* Verify repo catalog counts against README.md and AGENTS.md.
|
||||
*
|
||||
* Usage:
|
||||
* node scripts/ci/catalog.js
|
||||
* node scripts/ci/catalog.js --json
|
||||
* node scripts/ci/catalog.js --md
|
||||
* node scripts/ci/catalog.js --text
|
||||
* node scripts/ci/catalog.js --write --text
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -18,10 +17,6 @@ const path = require('path');
|
||||
const ROOT = path.join(__dirname, '../..');
|
||||
const README_PATH = path.join(ROOT, 'README.md');
|
||||
const AGENTS_PATH = path.join(ROOT, 'AGENTS.md');
|
||||
const README_ZH_CN_PATH = path.join(ROOT, 'README.zh-CN.md');
|
||||
const DOCS_ZH_CN_README_PATH = path.join(ROOT, 'docs', 'zh-CN', 'README.md');
|
||||
const DOCS_ZH_CN_AGENTS_PATH = path.join(ROOT, 'docs', 'zh-CN', 'AGENTS.md');
|
||||
const WRITE_MODE = process.argv.includes('--write');
|
||||
|
||||
const OUTPUT_MODE = process.argv.includes('--md')
|
||||
? 'md'
|
||||
@@ -48,9 +43,8 @@ function listMatchingFiles(relativeDir, matcher) {
|
||||
function buildCatalog() {
|
||||
const agents = listMatchingFiles('agents', entry => entry.isFile() && entry.name.endsWith('.md'));
|
||||
const commands = listMatchingFiles('commands', entry => entry.isFile() && entry.name.endsWith('.md'));
|
||||
const skills = listMatchingFiles('skills', entry => (
|
||||
entry.isDirectory() && fs.existsSync(path.join(ROOT, 'skills', entry.name, 'SKILL.md'))
|
||||
)).map(skillDir => `${skillDir}/SKILL.md`);
|
||||
const skills = listMatchingFiles('skills', entry => entry.isDirectory() && fs.existsSync(path.join(ROOT, 'skills', entry.name, 'SKILL.md')))
|
||||
.map(skillDir => `${skillDir}/SKILL.md`);
|
||||
|
||||
return {
|
||||
agents: { count: agents.length, files: agents, glob: 'agents/*.md' },
|
||||
@@ -67,22 +61,6 @@ function readFileOrThrow(filePath) {
|
||||
}
|
||||
}
|
||||
|
||||
function writeFileOrThrow(filePath, content) {
|
||||
try {
|
||||
fs.writeFileSync(filePath, content, 'utf8');
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to write ${path.basename(filePath)}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function replaceOrThrow(content, regex, replacer, source) {
|
||||
if (!regex.test(content)) {
|
||||
throw new Error(`${source} is missing the expected catalog marker`);
|
||||
}
|
||||
|
||||
return content.replace(regex, replacer);
|
||||
}
|
||||
|
||||
function parseReadmeExpectations(readmeContent) {
|
||||
const expectations = [];
|
||||
|
||||
@@ -117,120 +95,6 @@ function parseReadmeExpectations(readmeContent) {
|
||||
});
|
||||
}
|
||||
|
||||
const parityPatterns = [
|
||||
{
|
||||
category: 'agents',
|
||||
regex: /^\|\s*(?:\*\*)?Agents(?:\*\*)?\s*\|\s*(\d+)\s*\|\s*Shared\s*\(AGENTS\.md\)\s*\|\s*Shared\s*\(AGENTS\.md\)\s*\|\s*12\s*\|$/im,
|
||||
source: 'README.md parity table'
|
||||
},
|
||||
{
|
||||
category: 'commands',
|
||||
regex: /^\|\s*(?:\*\*)?Commands(?:\*\*)?\s*\|\s*(\d+)\s*\|\s*Shared\s*\|\s*Instruction-based\s*\|\s*31\s*\|$/im,
|
||||
source: 'README.md parity table'
|
||||
},
|
||||
{
|
||||
category: 'skills',
|
||||
regex: /^\|\s*(?:\*\*)?Skills(?:\*\*)?\s*\|\s*(\d+)\s*\|\s*Shared\s*\|\s*10\s*\(native format\)\s*\|\s*37\s*\|$/im,
|
||||
source: 'README.md parity table'
|
||||
}
|
||||
];
|
||||
|
||||
for (const pattern of parityPatterns) {
|
||||
const match = readmeContent.match(pattern.regex);
|
||||
if (!match) {
|
||||
throw new Error(`${pattern.source} is missing the ${pattern.category} row`);
|
||||
}
|
||||
|
||||
expectations.push({
|
||||
category: pattern.category,
|
||||
mode: 'exact',
|
||||
expected: Number(match[1]),
|
||||
source: `${pattern.source} (${pattern.category})`
|
||||
});
|
||||
}
|
||||
|
||||
return expectations;
|
||||
}
|
||||
|
||||
function parseZhRootReadmeExpectations(readmeContent) {
|
||||
const match = readmeContent.match(/你现在可以使用\s+(\d+)\s+个代理、\s*(\d+)\s*个技能和\s*(\d+)\s*个命令/i);
|
||||
if (!match) {
|
||||
throw new Error('README.zh-CN.md is missing the quick-start catalog summary');
|
||||
}
|
||||
|
||||
return [
|
||||
{ category: 'agents', mode: 'exact', expected: Number(match[1]), source: 'README.zh-CN.md quick-start summary' },
|
||||
{ category: 'skills', mode: 'exact', expected: Number(match[2]), source: 'README.zh-CN.md quick-start summary' },
|
||||
{ category: 'commands', mode: 'exact', expected: Number(match[3]), source: 'README.zh-CN.md quick-start summary' }
|
||||
];
|
||||
}
|
||||
|
||||
function parseZhDocsReadmeExpectations(readmeContent) {
|
||||
const expectations = [];
|
||||
|
||||
const quickStartMatch = readmeContent.match(/你现在可以使用\s+(\d+)\s+个智能体、\s*(\d+)\s*项技能和\s*(\d+)\s*个命令了/i);
|
||||
if (!quickStartMatch) {
|
||||
throw new Error('docs/zh-CN/README.md is missing the quick-start catalog summary');
|
||||
}
|
||||
|
||||
expectations.push(
|
||||
{ category: 'agents', mode: 'exact', expected: Number(quickStartMatch[1]), source: 'docs/zh-CN/README.md quick-start summary' },
|
||||
{ category: 'skills', mode: 'exact', expected: Number(quickStartMatch[2]), source: 'docs/zh-CN/README.md quick-start summary' },
|
||||
{ category: 'commands', mode: 'exact', expected: Number(quickStartMatch[3]), source: 'docs/zh-CN/README.md quick-start summary' }
|
||||
);
|
||||
|
||||
const tablePatterns = [
|
||||
{ category: 'agents', regex: /\|\s*智能体\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s*个\s*\|/i, source: 'docs/zh-CN/README.md comparison table' },
|
||||
{ category: 'commands', regex: /\|\s*命令\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s*个\s*\|/i, source: 'docs/zh-CN/README.md comparison table' },
|
||||
{ category: 'skills', regex: /\|\s*技能\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s*项\s*\|/i, source: 'docs/zh-CN/README.md comparison table' }
|
||||
];
|
||||
|
||||
for (const pattern of tablePatterns) {
|
||||
const match = readmeContent.match(pattern.regex);
|
||||
if (!match) {
|
||||
throw new Error(`${pattern.source} is missing the ${pattern.category} row`);
|
||||
}
|
||||
|
||||
expectations.push({
|
||||
category: pattern.category,
|
||||
mode: 'exact',
|
||||
expected: Number(match[1]),
|
||||
source: `${pattern.source} (${pattern.category})`
|
||||
});
|
||||
}
|
||||
|
||||
const parityPatterns = [
|
||||
{
|
||||
category: 'agents',
|
||||
regex: /^\|\s*(?:\*\*)?智能体(?:\*\*)?\s*\|\s*(\d+)\s*\|\s*共享\s*\(AGENTS\.md\)\s*\|\s*共享\s*\(AGENTS\.md\)\s*\|\s*12\s*\|$/im,
|
||||
source: 'docs/zh-CN/README.md parity table'
|
||||
},
|
||||
{
|
||||
category: 'commands',
|
||||
regex: /^\|\s*(?:\*\*)?命令(?:\*\*)?\s*\|\s*(\d+)\s*\|\s*共享\s*\|\s*基于指令\s*\|\s*31\s*\|$/im,
|
||||
source: 'docs/zh-CN/README.md parity table'
|
||||
},
|
||||
{
|
||||
category: 'skills',
|
||||
regex: /^\|\s*(?:\*\*)?技能(?:\*\*)?\s*\|\s*(\d+)\s*\|\s*共享\s*\|\s*10\s*\(原生格式\)\s*\|\s*37\s*\|$/im,
|
||||
source: 'docs/zh-CN/README.md parity table'
|
||||
}
|
||||
];
|
||||
|
||||
for (const pattern of parityPatterns) {
|
||||
const match = readmeContent.match(pattern.regex);
|
||||
if (!match) {
|
||||
throw new Error(`${pattern.source} is missing the ${pattern.category} row`);
|
||||
}
|
||||
|
||||
expectations.push({
|
||||
category: pattern.category,
|
||||
mode: 'exact',
|
||||
expected: Number(match[1]),
|
||||
source: `${pattern.source} (${pattern.category})`
|
||||
});
|
||||
}
|
||||
|
||||
return expectations;
|
||||
}
|
||||
|
||||
@@ -289,61 +153,6 @@ function parseAgentsDocExpectations(agentsContent) {
|
||||
return expectations;
|
||||
}
|
||||
|
||||
function parseZhAgentsDocExpectations(agentsContent) {
|
||||
const summaryMatch = agentsContent.match(/提供\s+(\d+)\s+个专业代理、\s*(\d+)(\+)?\s*项技能、\s*(\d+)\s+条命令/i);
|
||||
if (!summaryMatch) {
|
||||
throw new Error('docs/zh-CN/AGENTS.md is missing the catalog summary line');
|
||||
}
|
||||
|
||||
const expectations = [
|
||||
{ category: 'agents', mode: 'exact', expected: Number(summaryMatch[1]), source: 'docs/zh-CN/AGENTS.md summary' },
|
||||
{
|
||||
category: 'skills',
|
||||
mode: summaryMatch[3] ? 'minimum' : 'exact',
|
||||
expected: Number(summaryMatch[2]),
|
||||
source: 'docs/zh-CN/AGENTS.md summary'
|
||||
},
|
||||
{ category: 'commands', mode: 'exact', expected: Number(summaryMatch[4]), source: 'docs/zh-CN/AGENTS.md summary' }
|
||||
];
|
||||
|
||||
const structurePatterns = [
|
||||
{
|
||||
category: 'agents',
|
||||
mode: 'exact',
|
||||
regex: /^\s*agents\/\s*[—–-]\s*(\d+)\s+个专业子代理\s*$/im,
|
||||
source: 'docs/zh-CN/AGENTS.md project structure'
|
||||
},
|
||||
{
|
||||
category: 'skills',
|
||||
mode: 'minimum',
|
||||
regex: /^\s*skills\/\s*[—–-]\s*(\d+)(\+)?\s+个工作流技能和领域知识\s*$/im,
|
||||
source: 'docs/zh-CN/AGENTS.md project structure'
|
||||
},
|
||||
{
|
||||
category: 'commands',
|
||||
mode: 'exact',
|
||||
regex: /^\s*commands\/\s*[—–-]\s*(\d+)\s+个斜杠命令\s*$/im,
|
||||
source: 'docs/zh-CN/AGENTS.md project structure'
|
||||
}
|
||||
];
|
||||
|
||||
for (const pattern of structurePatterns) {
|
||||
const match = agentsContent.match(pattern.regex);
|
||||
if (!match) {
|
||||
throw new Error(`${pattern.source} is missing the ${pattern.category} entry`);
|
||||
}
|
||||
|
||||
expectations.push({
|
||||
category: pattern.category,
|
||||
mode: pattern.mode === 'minimum' && match[2] ? 'minimum' : pattern.mode,
|
||||
expected: Number(match[1]),
|
||||
source: `${pattern.source} (${pattern.category})`
|
||||
});
|
||||
}
|
||||
|
||||
return expectations;
|
||||
}
|
||||
|
||||
function evaluateExpectations(catalog, expectations) {
|
||||
return expectations.map(expectation => {
|
||||
const actual = catalog[expectation.category].count;
|
||||
@@ -364,208 +173,6 @@ function formatExpectation(expectation) {
|
||||
return `${expectation.source}: ${expectation.category} documented ${comparator} ${expectation.expected}, actual ${expectation.actual}`;
|
||||
}
|
||||
|
||||
function syncEnglishReadme(content, catalog) {
|
||||
let nextContent = content;
|
||||
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/(access to\s+)(\d+)(\s+agents,\s+)(\d+)(\s+skills,\s+and\s+)(\d+)(\s+commands)/i,
|
||||
(_, prefix, __, agentsSuffix, ___, skillsSuffix, ____, commandsSuffix) =>
|
||||
`${prefix}${catalog.agents.count}${agentsSuffix}${catalog.skills.count}${skillsSuffix}${catalog.commands.count}${commandsSuffix}`,
|
||||
'README.md quick-start summary'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/(\|\s*(?:\*\*)?Agents(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?)(\d+)(\s+agents\s*\|)/i,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.agents.count}${suffix}`,
|
||||
'README.md comparison table (agents)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/(\|\s*(?:\*\*)?Commands(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?)(\d+)(\s+commands\s*\|)/i,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.commands.count}${suffix}`,
|
||||
'README.md comparison table (commands)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/(\|\s*(?:\*\*)?Skills(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?)(\d+)(\s+skills\s*\|)/i,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.skills.count}${suffix}`,
|
||||
'README.md comparison table (skills)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/^(\|\s*(?:\*\*)?Agents(?:\*\*)?\s*\|\s*)(\d+)(\s*\|\s*Shared\s*\(AGENTS\.md\)\s*\|\s*Shared\s*\(AGENTS\.md\)\s*\|\s*12\s*\|)$/im,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.agents.count}${suffix}`,
|
||||
'README.md parity table (agents)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/^(\|\s*(?:\*\*)?Commands(?:\*\*)?\s*\|\s*)(\d+)(\s*\|\s*Shared\s*\|\s*Instruction-based\s*\|\s*31\s*\|)$/im,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.commands.count}${suffix}`,
|
||||
'README.md parity table (commands)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/^(\|\s*(?:\*\*)?Skills(?:\*\*)?\s*\|\s*)(\d+)(\s*\|\s*Shared\s*\|\s*10\s*\(native format\)\s*\|\s*37\s*\|)$/im,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.skills.count}${suffix}`,
|
||||
'README.md parity table (skills)'
|
||||
);
|
||||
|
||||
return nextContent;
|
||||
}
|
||||
|
||||
function syncEnglishAgents(content, catalog) {
|
||||
let nextContent = content;
|
||||
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/(providing\s+)(\d+)(\s+specialized agents,\s+)(\d+)(\+?)(\s+skills,\s+)(\d+)(\s+commands)/i,
|
||||
(_, prefix, __, agentsSuffix, ___, skillsPlus, skillsSuffix, ____, commandsSuffix) =>
|
||||
`${prefix}${catalog.agents.count}${agentsSuffix}${catalog.skills.count}${skillsPlus}${skillsSuffix}${catalog.commands.count}${commandsSuffix}`,
|
||||
'AGENTS.md summary'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/^(\s*agents\/\s*[—–-]\s*)(\d+)(\s+specialized subagents\s*)$/im,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.agents.count}${suffix}`,
|
||||
'AGENTS.md project structure (agents)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/^(\s*skills\/\s*[—–-]\s*)(\d+)(\+?)(\s+workflow skills and domain knowledge\s*)$/im,
|
||||
(_, prefix, __, plus, suffix) => `${prefix}${catalog.skills.count}${plus}${suffix}`,
|
||||
'AGENTS.md project structure (skills)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/^(\s*commands\/\s*[—–-]\s*)(\d+)(\s+slash commands\s*)$/im,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.commands.count}${suffix}`,
|
||||
'AGENTS.md project structure (commands)'
|
||||
);
|
||||
|
||||
return nextContent;
|
||||
}
|
||||
|
||||
function syncZhRootReadme(content, catalog) {
|
||||
return replaceOrThrow(
|
||||
content,
|
||||
/(你现在可以使用\s+)(\d+)(\s+个代理、\s*)(\d+)(\s*个技能和\s*)(\d+)(\s*个命令[。.!!]?)/i,
|
||||
(_, prefix, __, agentsSuffix, ___, skillsSuffix, ____, commandsSuffix) =>
|
||||
`${prefix}${catalog.agents.count}${agentsSuffix}${catalog.skills.count}${skillsSuffix}${catalog.commands.count}${commandsSuffix}`,
|
||||
'README.zh-CN.md quick-start summary'
|
||||
);
|
||||
}
|
||||
|
||||
function syncZhDocsReadme(content, catalog) {
|
||||
let nextContent = content;
|
||||
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/(你现在可以使用\s+)(\d+)(\s+个智能体、\s*)(\d+)(\s*项技能和\s*)(\d+)(\s*个命令了[。.!!]?)/i,
|
||||
(_, prefix, __, agentsSuffix, ___, skillsSuffix, ____, commandsSuffix) =>
|
||||
`${prefix}${catalog.agents.count}${agentsSuffix}${catalog.skills.count}${skillsSuffix}${catalog.commands.count}${commandsSuffix}`,
|
||||
'docs/zh-CN/README.md quick-start summary'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/(\|\s*智能体\s*\|\s*(?:(?:PASS:|\u2705)\s*)?)(\d+)(\s*个\s*\|)/i,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.agents.count}${suffix}`,
|
||||
'docs/zh-CN/README.md comparison table (agents)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/(\|\s*命令\s*\|\s*(?:(?:PASS:|\u2705)\s*)?)(\d+)(\s*个\s*\|)/i,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.commands.count}${suffix}`,
|
||||
'docs/zh-CN/README.md comparison table (commands)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/(\|\s*技能\s*\|\s*(?:(?:PASS:|\u2705)\s*)?)(\d+)(\s*项\s*\|)/i,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.skills.count}${suffix}`,
|
||||
'docs/zh-CN/README.md comparison table (skills)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/^(\|\s*(?:\*\*)?智能体(?:\*\*)?\s*\|\s*)(\d+)(\s*\|\s*共享\s*\(AGENTS\.md\)\s*\|\s*共享\s*\(AGENTS\.md\)\s*\|\s*12\s*\|)$/im,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.agents.count}${suffix}`,
|
||||
'docs/zh-CN/README.md parity table (agents)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/^(\|\s*(?:\*\*)?命令(?:\*\*)?\s*\|\s*)(\d+)(\s*\|\s*共享\s*\|\s*基于指令\s*\|\s*31\s*\|)$/im,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.commands.count}${suffix}`,
|
||||
'docs/zh-CN/README.md parity table (commands)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/^(\|\s*(?:\*\*)?技能(?:\*\*)?\s*\|\s*)(\d+)(\s*\|\s*共享\s*\|\s*10\s*\(原生格式\)\s*\|\s*37\s*\|)$/im,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.skills.count}${suffix}`,
|
||||
'docs/zh-CN/README.md parity table (skills)'
|
||||
);
|
||||
|
||||
return nextContent;
|
||||
}
|
||||
|
||||
function syncZhAgents(content, catalog) {
|
||||
let nextContent = content;
|
||||
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/(提供\s+)(\d+)(\s+个专业代理、\s*)(\d+)(\+?)(\s*项技能、\s*)(\d+)(\s+条命令)/i,
|
||||
(_, prefix, __, agentsSuffix, ___, skillsPlus, skillsSuffix, ____, commandsSuffix) =>
|
||||
`${prefix}${catalog.agents.count}${agentsSuffix}${catalog.skills.count}${skillsPlus}${skillsSuffix}${catalog.commands.count}${commandsSuffix}`,
|
||||
'docs/zh-CN/AGENTS.md summary'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/^(\s*agents\/\s*[—–-]\s*)(\d+)(\s+个专业子代理\s*)$/im,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.agents.count}${suffix}`,
|
||||
'docs/zh-CN/AGENTS.md project structure (agents)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/^(\s*skills\/\s*[—–-]\s*)(\d+)(\+?)(\s+个工作流技能和领域知识\s*)$/im,
|
||||
(_, prefix, __, plus, suffix) => `${prefix}${catalog.skills.count}${plus}${suffix}`,
|
||||
'docs/zh-CN/AGENTS.md project structure (skills)'
|
||||
);
|
||||
nextContent = replaceOrThrow(
|
||||
nextContent,
|
||||
/^(\s*commands\/\s*[—–-]\s*)(\d+)(\s+个斜杠命令\s*)$/im,
|
||||
(_, prefix, __, suffix) => `${prefix}${catalog.commands.count}${suffix}`,
|
||||
'docs/zh-CN/AGENTS.md project structure (commands)'
|
||||
);
|
||||
|
||||
return nextContent;
|
||||
}
|
||||
|
||||
const DOCUMENT_SPECS = [
|
||||
{
|
||||
filePath: README_PATH,
|
||||
parseExpectations: parseReadmeExpectations,
|
||||
syncContent: syncEnglishReadme,
|
||||
},
|
||||
{
|
||||
filePath: AGENTS_PATH,
|
||||
parseExpectations: parseAgentsDocExpectations,
|
||||
syncContent: syncEnglishAgents,
|
||||
},
|
||||
{
|
||||
filePath: README_ZH_CN_PATH,
|
||||
parseExpectations: parseZhRootReadmeExpectations,
|
||||
syncContent: syncZhRootReadme,
|
||||
},
|
||||
{
|
||||
filePath: DOCS_ZH_CN_README_PATH,
|
||||
parseExpectations: parseZhDocsReadmeExpectations,
|
||||
syncContent: syncZhDocsReadme,
|
||||
},
|
||||
{
|
||||
filePath: DOCS_ZH_CN_AGENTS_PATH,
|
||||
parseExpectations: parseZhAgentsDocExpectations,
|
||||
syncContent: syncZhAgents,
|
||||
},
|
||||
];
|
||||
|
||||
function renderText(result) {
|
||||
console.log('Catalog counts:');
|
||||
console.log(`- agents: ${result.catalog.agents.count}`);
|
||||
@@ -608,20 +215,12 @@ function renderMarkdown(result) {
|
||||
|
||||
function main() {
|
||||
const catalog = buildCatalog();
|
||||
|
||||
if (WRITE_MODE) {
|
||||
for (const spec of DOCUMENT_SPECS) {
|
||||
const currentContent = readFileOrThrow(spec.filePath);
|
||||
const nextContent = spec.syncContent(currentContent, catalog);
|
||||
if (nextContent !== currentContent) {
|
||||
writeFileOrThrow(spec.filePath, nextContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const expectations = DOCUMENT_SPECS.flatMap(spec => (
|
||||
spec.parseExpectations(readFileOrThrow(spec.filePath))
|
||||
));
|
||||
const readmeContent = readFileOrThrow(README_PATH);
|
||||
const agentsContent = readFileOrThrow(AGENTS_PATH);
|
||||
const expectations = [
|
||||
...parseReadmeExpectations(readmeContent),
|
||||
...parseAgentsDocExpectations(agentsContent)
|
||||
];
|
||||
const checks = evaluateExpectations(catalog, expectations);
|
||||
const result = { catalog, checks };
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ NC='\033[0m'
|
||||
|
||||
log() { echo -e "${BLUE}[GAN-HARNESS]${NC} $*"; }
|
||||
ok() { echo -e "${GREEN}[✓]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[⚠]${NC} $*"; }
|
||||
fail() { echo -e "${RED}[✗]${NC} $*"; }
|
||||
phase() { echo -e "\n${PURPLE}═══════════════════════════════════════════════${NC}"; echo -e "${PURPLE} $*${NC}"; echo -e "${PURPLE}═══════════════════════════════════════════════${NC}\n"; }
|
||||
|
||||
@@ -159,7 +159,7 @@ for (( i=1; i<=MAX_ITERATIONS; i++ )); do
|
||||
log "━━━ Iteration $i / $MAX_ITERATIONS ━━━"
|
||||
|
||||
# ── GENERATE ──
|
||||
echo -e "${GREEN}>> GENERATOR (iteration $i)${NC}"
|
||||
echo -e "${GREEN}▶ GENERATOR (iteration $i)${NC}"
|
||||
|
||||
FEEDBACK_CONTEXT=""
|
||||
if [ $i -gt 1 ] && [ -f "${FEEDBACK_DIR}/feedback-$(printf '%03d' $((i-1))).md" ]; then
|
||||
@@ -181,7 +181,7 @@ Update gan-harness/generator-state.md." \
|
||||
ok "Generator completed iteration $i"
|
||||
|
||||
# ── EVALUATE ──
|
||||
echo -e "${RED}>> EVALUATOR (iteration $i)${NC}"
|
||||
echo -e "${RED}▶ EVALUATOR (iteration $i)${NC}"
|
||||
|
||||
claude -p --model "$EVALUATOR_MODEL" \
|
||||
--allowedTools "Read,Write,Bash,Grep,Glob" \
|
||||
@@ -217,7 +217,7 @@ Include the weighted TOTAL score in the format: | **TOTAL** | | | **X.X** |" \
|
||||
# ── CHECK PASS ──
|
||||
if score_passes "$SCORE" "$PASS_THRESHOLD"; then
|
||||
echo ""
|
||||
ok "PASSED at iteration $i with score $SCORE (threshold: $PASS_THRESHOLD)"
|
||||
ok "🎉 PASSED at iteration $i with score $SCORE (threshold: $PASS_THRESHOLD)"
|
||||
break
|
||||
fi
|
||||
|
||||
@@ -256,7 +256,7 @@ cat > "${HARNESS_DIR}/build-report.md" << EOF
|
||||
# GAN Harness Build Report
|
||||
|
||||
**Brief:** $BRIEF
|
||||
**Result:** $(score_passes "$FINAL_SCORE" "$PASS_THRESHOLD" && echo "PASS" || echo "FAIL")
|
||||
**Result:** $(score_passes "$FINAL_SCORE" "$PASS_THRESHOLD" && echo "✅ PASS" || echo "❌ FAIL")
|
||||
**Iterations:** $NUM_ITERATIONS / $MAX_ITERATIONS
|
||||
**Final Score:** $FINAL_SCORE / 10.0 (threshold: $PASS_THRESHOLD)
|
||||
**Elapsed:** $ELAPSED
|
||||
@@ -287,9 +287,9 @@ ok "Report written to ${HARNESS_DIR}/build-report.md"
|
||||
echo ""
|
||||
log "━━━ Final Results ━━━"
|
||||
if score_passes "$FINAL_SCORE" "$PASS_THRESHOLD"; then
|
||||
echo -e "${GREEN} Result: PASS${NC}"
|
||||
echo -e "${GREEN} Result: PASS ✅${NC}"
|
||||
else
|
||||
echo -e "${RED} Result: FAIL${NC}"
|
||||
echo -e "${RED} Result: FAIL ❌${NC}"
|
||||
fi
|
||||
echo -e " Score: ${CYAN}${FINAL_SCORE}${NC} / 10.0"
|
||||
echo -e " Iterations: ${NUM_ITERATIONS} / ${MAX_ITERATIONS}"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const { getInstallTargetAdapter, planInstallTargetScaffold } = require('./install-targets/registry');
|
||||
const { planInstallTargetScaffold } = require('./install-targets/registry');
|
||||
|
||||
const DEFAULT_REPO_ROOT = path.join(__dirname, '../..');
|
||||
const SUPPORTED_INSTALL_TARGETS = ['claude', 'cursor', 'antigravity', 'codex', 'gemini', 'opencode', 'codebuddy'];
|
||||
@@ -76,48 +76,6 @@ function dedupeStrings(values) {
|
||||
return [...new Set((Array.isArray(values) ? values : []).map(value => String(value).trim()).filter(Boolean))];
|
||||
}
|
||||
|
||||
function readOptionalStringOption(options, key) {
|
||||
if (
|
||||
!Object.prototype.hasOwnProperty.call(options, key)
|
||||
|| options[key] === null
|
||||
|| options[key] === undefined
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof options[key] !== 'string' || options[key].trim() === '') {
|
||||
throw new Error(`${key} must be a non-empty string when provided`);
|
||||
}
|
||||
|
||||
return options[key];
|
||||
}
|
||||
|
||||
function readModuleTargetsOrThrow(module) {
|
||||
const moduleId = module && module.id ? module.id : '<unknown>';
|
||||
const targets = module && module.targets;
|
||||
|
||||
if (!Array.isArray(targets)) {
|
||||
throw new Error(`Install module ${moduleId} has invalid targets; expected an array of supported target ids`);
|
||||
}
|
||||
|
||||
const normalizedTargets = targets.map(target => (
|
||||
typeof target === 'string' ? target.trim() : ''
|
||||
));
|
||||
|
||||
if (normalizedTargets.some(target => target.length === 0)) {
|
||||
throw new Error(`Install module ${moduleId} has invalid targets; expected an array of supported target ids`);
|
||||
}
|
||||
|
||||
const unsupportedTargets = normalizedTargets.filter(target => !SUPPORTED_INSTALL_TARGETS.includes(target));
|
||||
if (unsupportedTargets.length > 0) {
|
||||
throw new Error(
|
||||
`Install module ${moduleId} has unsupported targets: ${unsupportedTargets.join(', ')}`
|
||||
);
|
||||
}
|
||||
|
||||
return normalizedTargets;
|
||||
}
|
||||
|
||||
function assertKnownModuleIds(moduleIds, manifests) {
|
||||
const unknownModuleIds = dedupeStrings(moduleIds)
|
||||
.filter(moduleId => !manifests.modulesById.has(moduleId));
|
||||
@@ -167,11 +125,6 @@ function loadInstallManifests(options = {}) {
|
||||
? profilesData.profiles
|
||||
: {};
|
||||
const components = Array.isArray(componentsData.components) ? componentsData.components : [];
|
||||
|
||||
for (const module of modules) {
|
||||
readModuleTargetsOrThrow(module);
|
||||
}
|
||||
|
||||
const modulesById = new Map(modules.map(module => [module.id, module]));
|
||||
const componentsById = new Map(components.map(component => [component.id, component]));
|
||||
|
||||
@@ -408,16 +361,6 @@ function resolveInstallPlan(options = {}) {
|
||||
`Unknown install target: ${target}. Expected one of ${SUPPORTED_INSTALL_TARGETS.join(', ')}`
|
||||
);
|
||||
}
|
||||
const validatedProjectRoot = readOptionalStringOption(options, 'projectRoot');
|
||||
const validatedHomeDir = readOptionalStringOption(options, 'homeDir');
|
||||
const targetPlanningInput = target
|
||||
? {
|
||||
repoRoot: manifests.repoRoot,
|
||||
projectRoot: validatedProjectRoot || manifests.repoRoot,
|
||||
homeDir: validatedHomeDir || os.homedir(),
|
||||
}
|
||||
: null;
|
||||
const targetAdapter = target ? getInstallTargetAdapter(target) : null;
|
||||
|
||||
const effectiveRequestedIds = dedupeStrings(
|
||||
requestedModuleIds.filter(moduleId => !excludedModuleOwners.has(moduleId))
|
||||
@@ -453,13 +396,7 @@ function resolveInstallPlan(options = {}) {
|
||||
return;
|
||||
}
|
||||
|
||||
const supportsTarget = !target
|
||||
|| (
|
||||
readModuleTargetsOrThrow(module).includes(target)
|
||||
&& (!targetAdapter || targetAdapter.supportsModule(module, targetPlanningInput))
|
||||
);
|
||||
|
||||
if (!supportsTarget) {
|
||||
if (target && !module.targets.includes(target)) {
|
||||
if (dependencyOf) {
|
||||
skippedTargetIds.add(rootRequesterId || dependencyOf);
|
||||
return false;
|
||||
@@ -507,9 +444,9 @@ function resolveInstallPlan(options = {}) {
|
||||
const scaffoldPlan = target
|
||||
? planInstallTargetScaffold({
|
||||
target,
|
||||
repoRoot: targetPlanningInput.repoRoot,
|
||||
projectRoot: targetPlanningInput.projectRoot,
|
||||
homeDir: targetPlanningInput.homeDir,
|
||||
repoRoot: manifests.repoRoot,
|
||||
projectRoot: options.projectRoot || manifests.repoRoot,
|
||||
homeDir: options.homeDir || os.homedir(),
|
||||
modules: selectedModules,
|
||||
})
|
||||
: null;
|
||||
|
||||
@@ -4,28 +4,14 @@ const {
|
||||
createFlatRuleOperations,
|
||||
createInstallTargetAdapter,
|
||||
createManagedScaffoldOperation,
|
||||
normalizeRelativePath,
|
||||
} = require('./helpers');
|
||||
|
||||
const SUPPORTED_SOURCE_PREFIXES = ['rules', 'commands', 'agents', 'skills', '.agents', 'AGENTS.md'];
|
||||
|
||||
function supportsAntigravitySourcePath(sourceRelativePath) {
|
||||
const normalizedPath = normalizeRelativePath(sourceRelativePath);
|
||||
return SUPPORTED_SOURCE_PREFIXES.some(prefix => (
|
||||
normalizedPath === prefix || normalizedPath.startsWith(`${prefix}/`)
|
||||
));
|
||||
}
|
||||
|
||||
module.exports = createInstallTargetAdapter({
|
||||
id: 'antigravity-project',
|
||||
target: 'antigravity',
|
||||
kind: 'project',
|
||||
rootSegments: ['.agent'],
|
||||
installStatePathSegments: ['ecc-install-state.json'],
|
||||
supportsModule(module) {
|
||||
const paths = Array.isArray(module && module.paths) ? module.paths : [];
|
||||
return paths.length > 0;
|
||||
},
|
||||
planOperations(input, adapter) {
|
||||
const modules = Array.isArray(input.modules)
|
||||
? input.modules
|
||||
@@ -44,9 +30,7 @@ module.exports = createInstallTargetAdapter({
|
||||
|
||||
return modules.flatMap(module => {
|
||||
const paths = Array.isArray(module.paths) ? module.paths : [];
|
||||
return paths
|
||||
.filter(supportsAntigravitySourcePath)
|
||||
.flatMap(sourceRelativePath => {
|
||||
return paths.flatMap(sourceRelativePath => {
|
||||
if (sourceRelativePath === 'rules') {
|
||||
return createFlatRuleOperations({
|
||||
moduleId: module.id,
|
||||
@@ -78,8 +62,8 @@ module.exports = createInstallTargetAdapter({
|
||||
];
|
||||
}
|
||||
|
||||
return [adapter.createScaffoldOperation(module.id, sourceRelativePath, planningInput)];
|
||||
});
|
||||
return [adapter.createScaffoldOperation(module.id, sourceRelativePath, planningInput)];
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -276,13 +276,6 @@ function createInstallTargetAdapter(config) {
|
||||
input
|
||||
));
|
||||
},
|
||||
supportsModule(module, input = {}) {
|
||||
if (typeof config.supportsModule === 'function') {
|
||||
return config.supportsModule(module, input, adapter);
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
validate(input = {}) {
|
||||
if (typeof config.validate === 'function') {
|
||||
return config.validate(input, adapter);
|
||||
|
||||
@@ -48,14 +48,14 @@ This is the same dynamic as GANs (Generative Adversarial Networks): the Generato
|
||||
│ FEEDBACK LOOP │
|
||||
│ │
|
||||
│ ┌──────────┐ │
|
||||
│ │GENERATOR │--build-->│──┐
|
||||
│ │GENERATOR │──build──▶│──┐
|
||||
│ │(Opus 4.6)│ │ │
|
||||
│ └────▲─────┘ │ │
|
||||
│ │ │ │ live app
|
||||
│ feedback │ │
|
||||
│ │ │ │
|
||||
│ ┌────┴─────┐ │ │
|
||||
│ │EVALUATOR │<-test----│──┘
|
||||
│ │EVALUATOR │◀─test───│──┘
|
||||
│ │(Opus 4.6)│ │
|
||||
│ │+Playwright│ │
|
||||
│ └──────────┘ │
|
||||
|
||||
@@ -156,19 +156,12 @@ function runCatalogValidator(overrides = {}) {
|
||||
const validatorPath = path.join(validatorsDir, 'catalog.js');
|
||||
let source = fs.readFileSync(validatorPath, 'utf8');
|
||||
source = stripShebang(source);
|
||||
const argv = Array.isArray(overrides.argv) && overrides.argv.length > 0
|
||||
? overrides.argv
|
||||
: ['--text'];
|
||||
const argvPreamble = argv.map(arg => `process.argv.push(${JSON.stringify(arg)});`).join('\n');
|
||||
source = `${argvPreamble}\n${source}`;
|
||||
source = `process.argv.push('--text');\n${source}`;
|
||||
|
||||
const resolvedOverrides = {
|
||||
ROOT: repoRoot,
|
||||
README_PATH: path.join(repoRoot, 'README.md'),
|
||||
AGENTS_PATH: path.join(repoRoot, 'AGENTS.md'),
|
||||
README_ZH_CN_PATH: path.join(repoRoot, 'README.zh-CN.md'),
|
||||
DOCS_ZH_CN_README_PATH: path.join(repoRoot, 'docs', 'zh-CN', 'README.md'),
|
||||
DOCS_ZH_CN_AGENTS_PATH: path.join(repoRoot, 'docs', 'zh-CN', 'AGENTS.md'),
|
||||
...overrides,
|
||||
};
|
||||
|
||||
@@ -183,50 +176,29 @@ function runCatalogValidator(overrides = {}) {
|
||||
function writeCatalogFixture(testDir, options = {}) {
|
||||
const {
|
||||
readmeCounts = { agents: 1, skills: 1, commands: 1 },
|
||||
readmeTableCounts = readmeCounts,
|
||||
readmeParityCounts = readmeCounts,
|
||||
readmeUnrelatedSkillsCount = 16,
|
||||
summaryCounts = { agents: 1, skills: 1, commands: 1 },
|
||||
structureLines = [
|
||||
'agents/ — 1 specialized subagents',
|
||||
'skills/ — 1 workflow skills and domain knowledge',
|
||||
'commands/ — 1 slash commands',
|
||||
],
|
||||
zhRootReadmeCounts = { agents: 1, skills: 1, commands: 1 },
|
||||
zhDocsReadmeCounts = { agents: 1, skills: 1, commands: 1 },
|
||||
zhDocsTableCounts = zhDocsReadmeCounts,
|
||||
zhDocsParityCounts = zhDocsReadmeCounts,
|
||||
zhDocsUnrelatedSkillsCount = 16,
|
||||
zhAgentsSummaryCounts = { agents: 1, skills: 1, commands: 1 },
|
||||
zhAgentsStructureLines = [
|
||||
'agents/ — 1 个专业子代理',
|
||||
'skills/ — 1 个工作流技能和领域知识',
|
||||
'commands/ — 1 个斜杠命令',
|
||||
],
|
||||
} = options;
|
||||
|
||||
const readmePath = path.join(testDir, 'README.md');
|
||||
const agentsPath = path.join(testDir, 'AGENTS.md');
|
||||
const zhRootReadmePath = path.join(testDir, 'README.zh-CN.md');
|
||||
const zhDocsReadmePath = path.join(testDir, 'docs', 'zh-CN', 'README.md');
|
||||
const zhAgentsPath = path.join(testDir, 'docs', 'zh-CN', 'AGENTS.md');
|
||||
|
||||
fs.mkdirSync(path.join(testDir, 'agents'), { recursive: true });
|
||||
fs.mkdirSync(path.join(testDir, 'commands'), { recursive: true });
|
||||
fs.mkdirSync(path.join(testDir, 'skills', 'demo-skill'), { recursive: true });
|
||||
fs.mkdirSync(path.join(testDir, 'docs', 'zh-CN'), { recursive: true });
|
||||
|
||||
fs.writeFileSync(path.join(testDir, 'agents', 'planner.md'), '---\nmodel: sonnet\ntools: Read\n---\n# Planner');
|
||||
fs.writeFileSync(path.join(testDir, 'commands', 'plan.md'), '---\ndescription: Plan\n---\n# Plan');
|
||||
fs.writeFileSync(path.join(testDir, 'skills', 'demo-skill', 'SKILL.md'), '---\nname: demo-skill\ndescription: Demo skill\norigin: ECC\n---\n# Demo Skill');
|
||||
|
||||
fs.writeFileSync(readmePath, `Access to ${readmeCounts.agents} agents, ${readmeCounts.skills} skills, and ${readmeCounts.commands} commands.\n| Feature | Claude Code | Cursor IDE | Codex CLI | OpenCode |\n|---------|------------|------------|-----------|----------|\n| Agents | PASS: ${readmeTableCounts.agents} agents | Shared | Shared | 1 |\n| Commands | PASS: ${readmeTableCounts.commands} commands | Shared | Shared | 1 |\n| Skills | PASS: ${readmeTableCounts.skills} skills | Shared | Shared | 1 |\n\n| Feature | Count | Format |\n|-----------|-------|---------|\n| Skills | ${readmeUnrelatedSkillsCount} | .agents/skills/ |\n\n## Cross-Tool Feature Parity\n\n| Feature | Claude Code | Cursor IDE | Codex CLI | OpenCode |\n|---------|------------|------------|-----------|----------|\n| **Agents** | ${readmeParityCounts.agents} | Shared (AGENTS.md) | Shared (AGENTS.md) | 12 |\n| **Commands** | ${readmeParityCounts.commands} | Shared | Instruction-based | 31 |\n| **Skills** | ${readmeParityCounts.skills} | Shared | 10 (native format) | 37 |\n`);
|
||||
fs.writeFileSync(readmePath, `Access to ${readmeCounts.agents} agents, ${readmeCounts.skills} skills, and ${readmeCounts.commands} commands.\n| Feature | Claude Code | Cursor IDE | Codex CLI | OpenCode |\n|---------|------------|------------|-----------|----------|\n| Agents | PASS: ${readmeCounts.agents} agents | Shared | Shared | 1 |\n| Commands | PASS: ${readmeCounts.commands} commands | Shared | Shared | 1 |\n| Skills | PASS: ${readmeCounts.skills} skills | Shared | Shared | 1 |\n`);
|
||||
fs.writeFileSync(agentsPath, `This is a **production-ready AI coding plugin** providing ${summaryCounts.agents} specialized agents, ${summaryCounts.skills} skills, ${summaryCounts.commands} commands, and automated hook workflows for software development.\n\n\`\`\`\n${structureLines.join('\n')}\n\`\`\`\n`);
|
||||
fs.writeFileSync(zhRootReadmePath, `**完成!** 你现在可以使用 ${zhRootReadmeCounts.agents} 个代理、${zhRootReadmeCounts.skills} 个技能和 ${zhRootReadmeCounts.commands} 个命令。\n`);
|
||||
fs.writeFileSync(zhDocsReadmePath, `**搞定!** 你现在可以使用 ${zhDocsReadmeCounts.agents} 个智能体、${zhDocsReadmeCounts.skills} 项技能和 ${zhDocsReadmeCounts.commands} 个命令了。\n| 功能特性 | Claude Code | OpenCode | 状态 |\n|---------|-------------|----------|--------|\n| 智能体 | \u2705 ${zhDocsTableCounts.agents} 个 | \u2705 12 个 | **Claude Code 领先** |\n| 命令 | \u2705 ${zhDocsTableCounts.commands} 个 | \u2705 31 个 | **Claude Code 领先** |\n| 技能 | \u2705 ${zhDocsTableCounts.skills} 项 | \u2705 37 项 | **Claude Code 领先** |\n\n| 功能特性 | 数量 | 格式 |\n|-----------|-------|---------|\n| 技能 | ${zhDocsUnrelatedSkillsCount} | .agents/skills/ |\n\n## 跨工具功能对等\n\n| 功能特性 | Claude Code | Cursor IDE | Codex CLI | OpenCode |\n|---------|------------|------------|-----------|----------|\n| **智能体** | ${zhDocsParityCounts.agents} | 共享 (AGENTS.md) | 共享 (AGENTS.md) | 12 |\n| **命令** | ${zhDocsParityCounts.commands} | 共享 | 基于指令 | 31 |\n| **技能** | ${zhDocsParityCounts.skills} | 共享 | 10 (原生格式) | 37 |\n`);
|
||||
fs.writeFileSync(zhAgentsPath, `这是一个**生产就绪的 AI 编码插件**,提供 ${zhAgentsSummaryCounts.agents} 个专业代理、${zhAgentsSummaryCounts.skills} 项技能、${zhAgentsSummaryCounts.commands} 条命令以及自动化钩子工作流,用于软件开发。\n\n\`\`\`\n${zhAgentsStructureLines.join('\n')}\n\`\`\`\n`);
|
||||
|
||||
return { readmePath, agentsPath, zhRootReadmePath, zhDocsReadmePath, zhAgentsPath };
|
||||
return { readmePath, agentsPath };
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
@@ -369,41 +341,20 @@ function runTests() {
|
||||
|
||||
if (test('fails when README and AGENTS catalog counts drift', () => {
|
||||
const testDir = createTestDir();
|
||||
const {
|
||||
readmePath,
|
||||
agentsPath,
|
||||
zhRootReadmePath,
|
||||
zhDocsReadmePath,
|
||||
zhAgentsPath,
|
||||
} = writeCatalogFixture(testDir, {
|
||||
const { readmePath, agentsPath } = writeCatalogFixture(testDir, {
|
||||
readmeCounts: { agents: 99, skills: 99, commands: 99 },
|
||||
readmeTableCounts: { agents: 99, skills: 99, commands: 99 },
|
||||
readmeParityCounts: { agents: 99, skills: 99, commands: 99 },
|
||||
summaryCounts: { agents: 99, skills: 99, commands: 99 },
|
||||
structureLines: [
|
||||
'agents/ — 99 specialized subagents',
|
||||
'skills/ — 99 workflow skills and domain knowledge',
|
||||
'commands/ — 99 slash commands',
|
||||
],
|
||||
zhRootReadmeCounts: { agents: 99, skills: 99, commands: 99 },
|
||||
zhDocsReadmeCounts: { agents: 99, skills: 99, commands: 99 },
|
||||
zhDocsTableCounts: { agents: 99, skills: 99, commands: 99 },
|
||||
zhDocsParityCounts: { agents: 99, skills: 99, commands: 99 },
|
||||
zhAgentsSummaryCounts: { agents: 99, skills: 99, commands: 99 },
|
||||
zhAgentsStructureLines: [
|
||||
'agents/ — 99 个专业子代理',
|
||||
'skills/ — 99 个工作流技能和领域知识',
|
||||
'commands/ — 99 个斜杠命令',
|
||||
],
|
||||
});
|
||||
|
||||
const result = runCatalogValidator({
|
||||
ROOT: testDir,
|
||||
README_PATH: readmePath,
|
||||
AGENTS_PATH: agentsPath,
|
||||
README_ZH_CN_PATH: zhRootReadmePath,
|
||||
DOCS_ZH_CN_README_PATH: zhDocsReadmePath,
|
||||
DOCS_ZH_CN_AGENTS_PATH: zhAgentsPath,
|
||||
});
|
||||
|
||||
assert.strictEqual(result.code, 1, 'Should fail when catalog counts drift');
|
||||
@@ -411,154 +362,20 @@ function runTests() {
|
||||
cleanupTestDir(testDir);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('fails when README parity table counts drift', () => {
|
||||
const testDir = createTestDir();
|
||||
const {
|
||||
readmePath,
|
||||
agentsPath,
|
||||
zhRootReadmePath,
|
||||
zhDocsReadmePath,
|
||||
zhAgentsPath,
|
||||
} = writeCatalogFixture(testDir, {
|
||||
readmeCounts: { agents: 1, skills: 1, commands: 1 },
|
||||
readmeTableCounts: { agents: 1, skills: 1, commands: 1 },
|
||||
readmeParityCounts: { agents: 9, skills: 8, commands: 7 },
|
||||
summaryCounts: { agents: 1, skills: 1, commands: 1 },
|
||||
});
|
||||
|
||||
const result = runCatalogValidator({
|
||||
ROOT: testDir,
|
||||
README_PATH: readmePath,
|
||||
AGENTS_PATH: agentsPath,
|
||||
README_ZH_CN_PATH: zhRootReadmePath,
|
||||
DOCS_ZH_CN_README_PATH: zhDocsReadmePath,
|
||||
DOCS_ZH_CN_AGENTS_PATH: zhAgentsPath,
|
||||
});
|
||||
|
||||
assert.strictEqual(result.code, 1, 'Should fail when README parity table drifts');
|
||||
assert.ok(
|
||||
(result.stdout + result.stderr).includes('README.md parity table'),
|
||||
'Should mention the README parity table mismatch'
|
||||
);
|
||||
cleanupTestDir(testDir);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('fails when a tracked catalog document is missing', () => {
|
||||
const testDir = createTestDir();
|
||||
const {
|
||||
readmePath,
|
||||
agentsPath,
|
||||
zhRootReadmePath,
|
||||
zhDocsReadmePath,
|
||||
} = writeCatalogFixture(testDir);
|
||||
const missingZhAgentsPath = path.join(testDir, 'docs', 'zh-CN', 'AGENTS.md');
|
||||
fs.rmSync(missingZhAgentsPath);
|
||||
|
||||
const result = runCatalogValidator({
|
||||
ROOT: testDir,
|
||||
README_PATH: readmePath,
|
||||
AGENTS_PATH: agentsPath,
|
||||
README_ZH_CN_PATH: zhRootReadmePath,
|
||||
DOCS_ZH_CN_README_PATH: zhDocsReadmePath,
|
||||
DOCS_ZH_CN_AGENTS_PATH: missingZhAgentsPath,
|
||||
});
|
||||
|
||||
assert.strictEqual(result.code, 1, 'Should fail when a tracked doc is missing');
|
||||
assert.ok(
|
||||
(result.stdout + result.stderr).includes('Failed to read AGENTS.md'),
|
||||
'Should mention the missing tracked document'
|
||||
);
|
||||
cleanupTestDir(testDir);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('syncs tracked catalog docs in write mode without rewriting unrelated tables', () => {
|
||||
const testDir = createTestDir();
|
||||
const {
|
||||
readmePath,
|
||||
agentsPath,
|
||||
zhRootReadmePath,
|
||||
zhDocsReadmePath,
|
||||
zhAgentsPath,
|
||||
} = writeCatalogFixture(testDir, {
|
||||
readmeCounts: { agents: 9, skills: 9, commands: 9 },
|
||||
readmeTableCounts: { agents: 8, skills: 8, commands: 8 },
|
||||
readmeParityCounts: { agents: 7, skills: 7, commands: 7 },
|
||||
summaryCounts: { agents: 6, skills: 6, commands: 6 },
|
||||
zhRootReadmeCounts: { agents: 10, skills: 10, commands: 10 },
|
||||
zhDocsReadmeCounts: { agents: 11, skills: 11, commands: 11 },
|
||||
zhDocsTableCounts: { agents: 12, skills: 12, commands: 12 },
|
||||
zhDocsParityCounts: { agents: 13, skills: 13, commands: 13 },
|
||||
zhAgentsSummaryCounts: { agents: 14, skills: 14, commands: 14 },
|
||||
zhAgentsStructureLines: [
|
||||
'agents/ — 15 个专业子代理',
|
||||
'skills/ — 16 个工作流技能和领域知识',
|
||||
'commands/ — 17 个斜杠命令',
|
||||
],
|
||||
});
|
||||
|
||||
const result = runCatalogValidator({
|
||||
argv: ['--write', '--text'],
|
||||
ROOT: testDir,
|
||||
README_PATH: readmePath,
|
||||
AGENTS_PATH: agentsPath,
|
||||
README_ZH_CN_PATH: zhRootReadmePath,
|
||||
DOCS_ZH_CN_README_PATH: zhDocsReadmePath,
|
||||
DOCS_ZH_CN_AGENTS_PATH: zhAgentsPath,
|
||||
});
|
||||
|
||||
assert.strictEqual(result.code, 0, `Should sync and pass, got stderr: ${result.stderr}`);
|
||||
|
||||
const readme = fs.readFileSync(readmePath, 'utf8');
|
||||
const agentsDoc = fs.readFileSync(agentsPath, 'utf8');
|
||||
const zhRootReadme = fs.readFileSync(zhRootReadmePath, 'utf8');
|
||||
const zhDocsReadme = fs.readFileSync(zhDocsReadmePath, 'utf8');
|
||||
const zhAgentsDoc = fs.readFileSync(zhAgentsPath, 'utf8');
|
||||
|
||||
assert.ok(readme.includes('Access to 1 agents, 1 skills, and 1 commands.'), 'Should sync README quick-start summary');
|
||||
assert.ok(readme.includes('| Agents | PASS: 1 agents |'), 'Should sync README comparison table');
|
||||
assert.ok(readme.includes('| Skills | 16 | .agents/skills/ |'), 'Should not rewrite unrelated README tables');
|
||||
assert.ok(readme.includes('| **Agents** | 1 | Shared (AGENTS.md) | Shared (AGENTS.md) | 12 |'), 'Should sync README parity table');
|
||||
assert.ok(agentsDoc.includes('providing 1 specialized agents, 1 skills, 1 commands'), 'Should sync AGENTS summary');
|
||||
assert.ok(agentsDoc.includes('skills/ — 1 workflow skills and domain knowledge'), 'Should sync AGENTS structure');
|
||||
assert.ok(zhRootReadme.includes('你现在可以使用 1 个代理、1 个技能和 1 个命令'), 'Should sync README.zh-CN quick-start summary');
|
||||
assert.ok(zhDocsReadme.includes('你现在可以使用 1 个智能体、1 项技能和 1 个命令了'), 'Should sync docs/zh-CN/README quick-start summary');
|
||||
assert.ok(zhDocsReadme.includes('| 智能体 | \u2705 1 个 |'), 'Should sync docs/zh-CN/README comparison table');
|
||||
assert.ok(zhDocsReadme.includes('| 技能 | 16 | .agents/skills/ |'), 'Should not rewrite unrelated docs/zh-CN/README tables');
|
||||
assert.ok(zhDocsReadme.includes('| **智能体** | 1 | 共享 (AGENTS.md) | 共享 (AGENTS.md) | 12 |'), 'Should sync docs/zh-CN/README parity table');
|
||||
assert.ok(zhAgentsDoc.includes('提供 1 个专业代理、1 项技能、1 条命令'), 'Should sync docs/zh-CN/AGENTS summary');
|
||||
assert.ok(zhAgentsDoc.includes('commands/ — 1 个斜杠命令'), 'Should sync docs/zh-CN/AGENTS structure');
|
||||
|
||||
cleanupTestDir(testDir);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('accepts AGENTS project structure entries with varied spacing and dash styles', () => {
|
||||
const testDir = createTestDir();
|
||||
const {
|
||||
readmePath,
|
||||
agentsPath,
|
||||
zhRootReadmePath,
|
||||
zhDocsReadmePath,
|
||||
zhAgentsPath,
|
||||
} = writeCatalogFixture(testDir, {
|
||||
const { readmePath, agentsPath } = writeCatalogFixture(testDir, {
|
||||
structureLines: [
|
||||
' agents/ - 1 specialized subagents ',
|
||||
'\tskills/\t–\t1+ workflow skills and domain knowledge\t',
|
||||
' commands/ — 1 slash commands ',
|
||||
],
|
||||
zhAgentsStructureLines: [
|
||||
' agents/ - 1 个专业子代理 ',
|
||||
'\tskills/\t–\t1+ 个工作流技能和领域知识\t',
|
||||
' commands/ — 1 个斜杠命令 ',
|
||||
],
|
||||
});
|
||||
|
||||
const result = runCatalogValidator({
|
||||
ROOT: testDir,
|
||||
README_PATH: readmePath,
|
||||
AGENTS_PATH: agentsPath,
|
||||
README_ZH_CN_PATH: zhRootReadmePath,
|
||||
DOCS_ZH_CN_README_PATH: zhDocsReadmePath,
|
||||
DOCS_ZH_CN_AGENTS_PATH: zhAgentsPath,
|
||||
});
|
||||
|
||||
assert.strictEqual(result.code, 0, `Should accept formatting variations, got stderr: ${result.stderr}`);
|
||||
|
||||
@@ -25,7 +25,7 @@ async function runTests() {
|
||||
try {
|
||||
store = await import(pathToFileURL(storePath).href)
|
||||
} catch (err) {
|
||||
console.log('\n[warn] Skipping: build .opencode first (cd .opencode && npm run build)\n')
|
||||
console.log('\n⚠ Skipping: build .opencode first (cd .opencode && npm run build)\n')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
|
||||
@@ -253,142 +253,46 @@ function runTests() {
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('validates projectRoot and homeDir option types before adapter planning', () => {
|
||||
assert.throws(
|
||||
() => resolveInstallPlan({ profileId: 'core', target: 'cursor', projectRoot: 42 }),
|
||||
/projectRoot must be a non-empty string when provided/
|
||||
);
|
||||
assert.throws(
|
||||
() => resolveInstallPlan({ profileId: 'core', target: 'claude', homeDir: {} }),
|
||||
/homeDir must be a non-empty string when provided/
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('skips a requested module when its dependency chain does not support the target', () => {
|
||||
const repoRoot = createTestRepo();
|
||||
try {
|
||||
writeJson(path.join(repoRoot, 'manifests', 'install-modules.json'), {
|
||||
version: 1,
|
||||
modules: [
|
||||
{
|
||||
id: 'parent',
|
||||
kind: 'skills',
|
||||
description: 'Parent',
|
||||
paths: ['parent'],
|
||||
targets: ['claude'],
|
||||
dependencies: ['child'],
|
||||
defaultInstall: false,
|
||||
cost: 'light',
|
||||
stability: 'stable'
|
||||
},
|
||||
{
|
||||
id: 'child',
|
||||
kind: 'skills',
|
||||
description: 'Child',
|
||||
paths: ['child'],
|
||||
targets: ['cursor'],
|
||||
dependencies: [],
|
||||
defaultInstall: false,
|
||||
cost: 'light',
|
||||
stability: 'stable'
|
||||
}
|
||||
]
|
||||
});
|
||||
writeJson(path.join(repoRoot, 'manifests', 'install-profiles.json'), {
|
||||
version: 1,
|
||||
profiles: {
|
||||
core: { description: 'Core', modules: ['parent'] }
|
||||
writeJson(path.join(repoRoot, 'manifests', 'install-modules.json'), {
|
||||
version: 1,
|
||||
modules: [
|
||||
{
|
||||
id: 'parent',
|
||||
kind: 'skills',
|
||||
description: 'Parent',
|
||||
paths: ['parent'],
|
||||
targets: ['claude'],
|
||||
dependencies: ['child'],
|
||||
defaultInstall: false,
|
||||
cost: 'light',
|
||||
stability: 'stable'
|
||||
},
|
||||
{
|
||||
id: 'child',
|
||||
kind: 'skills',
|
||||
description: 'Child',
|
||||
paths: ['child'],
|
||||
targets: ['cursor'],
|
||||
dependencies: [],
|
||||
defaultInstall: false,
|
||||
cost: 'light',
|
||||
stability: 'stable'
|
||||
}
|
||||
});
|
||||
]
|
||||
});
|
||||
writeJson(path.join(repoRoot, 'manifests', 'install-profiles.json'), {
|
||||
version: 1,
|
||||
profiles: {
|
||||
core: { description: 'Core', modules: ['parent'] }
|
||||
}
|
||||
});
|
||||
|
||||
const plan = resolveInstallPlan({ repoRoot, profileId: 'core', target: 'claude' });
|
||||
assert.deepStrictEqual(plan.selectedModuleIds, []);
|
||||
assert.deepStrictEqual(plan.skippedModuleIds, ['parent']);
|
||||
} finally {
|
||||
cleanupTestRepo(repoRoot);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('fails fast when install manifest module targets is not an array', () => {
|
||||
const repoRoot = createTestRepo();
|
||||
try {
|
||||
writeJson(path.join(repoRoot, 'manifests', 'install-modules.json'), {
|
||||
version: 1,
|
||||
modules: [
|
||||
{
|
||||
id: 'parent',
|
||||
kind: 'skills',
|
||||
description: 'Parent',
|
||||
paths: ['parent'],
|
||||
targets: 'claude',
|
||||
dependencies: [],
|
||||
defaultInstall: false,
|
||||
cost: 'light',
|
||||
stability: 'stable'
|
||||
}
|
||||
]
|
||||
});
|
||||
writeJson(path.join(repoRoot, 'manifests', 'install-profiles.json'), {
|
||||
version: 1,
|
||||
profiles: {
|
||||
core: { description: 'Core', modules: ['parent'] }
|
||||
}
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => resolveInstallPlan({ repoRoot, profileId: 'core', target: 'claude' }),
|
||||
/Install module parent has invalid targets; expected an array of supported target ids/
|
||||
);
|
||||
} finally {
|
||||
cleanupTestRepo(repoRoot);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('keeps antigravity modules selected while filtering unsupported source paths', () => {
|
||||
const repoRoot = createTestRepo();
|
||||
try {
|
||||
writeJson(path.join(repoRoot, 'manifests', 'install-modules.json'), {
|
||||
version: 1,
|
||||
modules: [
|
||||
{
|
||||
id: 'unsupported-antigravity',
|
||||
kind: 'skills',
|
||||
description: 'Unsupported',
|
||||
paths: ['.cursor', 'skills/example'],
|
||||
targets: ['antigravity'],
|
||||
dependencies: [],
|
||||
defaultInstall: false,
|
||||
cost: 'light',
|
||||
stability: 'stable'
|
||||
}
|
||||
]
|
||||
});
|
||||
writeJson(path.join(repoRoot, 'manifests', 'install-profiles.json'), {
|
||||
version: 1,
|
||||
profiles: {
|
||||
core: { description: 'Core', modules: ['unsupported-antigravity'] }
|
||||
}
|
||||
});
|
||||
|
||||
const plan = resolveInstallPlan({
|
||||
repoRoot,
|
||||
profileId: 'core',
|
||||
target: 'antigravity',
|
||||
projectRoot: '/workspace/app',
|
||||
});
|
||||
assert.deepStrictEqual(plan.selectedModuleIds, ['unsupported-antigravity']);
|
||||
assert.deepStrictEqual(plan.skippedModuleIds, []);
|
||||
assert.ok(
|
||||
plan.operations.every(operation => operation.sourceRelativePath !== '.cursor'),
|
||||
'Unsupported antigravity paths should be filtered from planned operations'
|
||||
);
|
||||
assert.ok(
|
||||
plan.operations.some(operation => operation.sourceRelativePath === 'skills/example'),
|
||||
'Supported antigravity skill paths should still be planned'
|
||||
);
|
||||
} finally {
|
||||
cleanupTestRepo(repoRoot);
|
||||
}
|
||||
const plan = resolveInstallPlan({ repoRoot, profileId: 'core', target: 'claude' });
|
||||
assert.deepStrictEqual(plan.selectedModuleIds, []);
|
||||
assert.deepStrictEqual(plan.skippedModuleIds, ['parent']);
|
||||
cleanupTestRepo(repoRoot);
|
||||
})) passed++; else failed++;
|
||||
|
||||
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
|
||||
|
||||
Reference in New Issue
Block a user