wordpress-agent-kit 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/wp-bootstrap/SKILL.md +314 -0
- package/.agents/skills/wp-bootstrap/references/composer-setup.md +275 -0
- package/.agents/skills/wp-bootstrap/references/monorepo-patterns.md +184 -0
- package/.agents/skills/wp-bootstrap/scripts/bootstrap.sh +151 -0
- package/.agents/skills/wp-bootstrap/scripts/detect-structure.mjs +466 -0
- package/.agents/skills/wp-bootstrap/scripts/package-wp.sh +173 -0
- package/.agents/skills/wp-bootstrap/scripts/playground-start.sh +148 -0
- package/.agents/skills/wp-bootstrap/scripts/playground-verify.sh +165 -0
- package/.agents/skills/wp-bootstrap/scripts/setup-github.sh +417 -0
- package/{.github → .agents}/skills/wp-wpcli-and-ops/SKILL.md +11 -9
- package/.agents/skills/wp-wpengine/SKILL.md +462 -0
- package/.agents/skills/wp-wpengine/references/ci-gate.md +469 -0
- package/.agents/skills/wp-wpengine/references/github-actions-deploy.md +743 -0
- package/.agents/skills/wp-wpengine/scripts/ci-gate.sh +118 -0
- package/.agents/skills/wp-wpengine/scripts/wpe-check.sh +89 -0
- package/.agents/skills/wp-wpengine/scripts/wpe-preflight.sh +104 -0
- package/.github/agents/wp-architect.agent.md +1 -2
- package/.github/copilot-instructions.md +1 -1
- package/.github/instructions/wordpress-workflow.instructions.md +3 -3
- package/AGENTS.md +22 -10
- package/AGENTS.template.md +20 -10
- package/README.md +89 -85
- package/dist/cli.js +7 -1
- package/dist/commands/bootstrap.js +105 -0
- package/dist/commands/clean-skills.js +64 -0
- package/dist/commands/setup.js +6 -2
- package/dist/commands/sync-skills.js +3 -0
- package/dist/lib/api.js +165 -5
- package/dist/lib/bootstrap.js +352 -0
- package/dist/lib/installer.js +166 -2
- package/extensions/wp-agent-kit/index.ts +325 -10
- package/package.json +10 -14
- package/skills-custom/wp-bootstrap/SKILL.md +314 -0
- package/skills-custom/wp-bootstrap/references/composer-setup.md +275 -0
- package/skills-custom/wp-bootstrap/references/monorepo-patterns.md +184 -0
- package/skills-custom/wp-bootstrap/scripts/bootstrap.sh +151 -0
- package/skills-custom/wp-bootstrap/scripts/detect-structure.mjs +466 -0
- package/skills-custom/wp-bootstrap/scripts/package-wp.sh +173 -0
- package/skills-custom/wp-bootstrap/scripts/playground-start.sh +148 -0
- package/skills-custom/wp-bootstrap/scripts/playground-verify.sh +165 -0
- package/skills-custom/wp-bootstrap/scripts/setup-github.sh +417 -0
- package/skills-custom/wp-wpengine/SKILL.md +362 -27
- package/skills-custom/wp-wpengine/references/ci-gate.md +469 -0
- package/skills-custom/wp-wpengine/references/github-actions-deploy.md +743 -0
- package/skills-custom/wp-wpengine/scripts/ci-gate.sh +118 -0
- package/skills-custom/wp-wpengine/scripts/wpe-check.sh +89 -0
- package/skills-custom/wp-wpengine/scripts/wpe-preflight.sh +104 -0
- package/.github/skills/wp-wpengine/SKILL.md +0 -127
- package/.github/workflows/ci.yml +0 -44
- package/.husky/pre-commit +0 -7
- package/CLI_REVIEW.md +0 -250
- package/biome.json +0 -39
- /package/{.github → .agents}/skills/blueprint/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wordpress-router/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wordpress-router/references/decision-tree.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-api/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-api/references/delegate-helper-pattern.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-api/references/domain-vs-projection.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-api/references/error-code-vocabulary.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-api/references/grouping-heuristic.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-api/references/input-schema-gotchas.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-api/references/php-registration.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-api/references/plugin-family-patterns.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-api/references/rest-api.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-api/references/shared-core-service.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-audit/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-audit/references/audit-schema.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-audit/references/capability-gate-tracing.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-audit/references/controller-enumeration.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-verify/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-verify/references/annotation-correctness.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-verify/references/audit-schema-validation.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-verify/references/permission-roundtrip.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-verify/references/runtime-harness.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-verify/references/schema-lints.md +0 -0
- /package/{.github → .agents}/skills/wp-abilities-verify/references/static-enumeration.md +0 -0
- /package/{.github → .agents}/skills/wp-block-development/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-block-development/references/attributes-and-serialization.md +0 -0
- /package/{.github → .agents}/skills/wp-block-development/references/block-json.md +0 -0
- /package/{.github → .agents}/skills/wp-block-development/references/creating-new-blocks.md +0 -0
- /package/{.github → .agents}/skills/wp-block-development/references/debugging.md +0 -0
- /package/{.github → .agents}/skills/wp-block-development/references/deprecations.md +0 -0
- /package/{.github → .agents}/skills/wp-block-development/references/dynamic-rendering.md +0 -0
- /package/{.github → .agents}/skills/wp-block-development/references/inner-blocks.md +0 -0
- /package/{.github → .agents}/skills/wp-block-development/references/registration.md +0 -0
- /package/{.github → .agents}/skills/wp-block-development/references/supports-and-wrappers.md +0 -0
- /package/{.github → .agents}/skills/wp-block-development/references/tooling-and-testing.md +0 -0
- /package/{.github → .agents}/skills/wp-block-development/scripts/list_blocks.mjs +0 -0
- /package/{.github → .agents}/skills/wp-block-themes/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-block-themes/references/creating-new-block-theme.md +0 -0
- /package/{.github → .agents}/skills/wp-block-themes/references/debugging.md +0 -0
- /package/{.github → .agents}/skills/wp-block-themes/references/patterns.md +0 -0
- /package/{.github → .agents}/skills/wp-block-themes/references/style-variations.md +0 -0
- /package/{.github → .agents}/skills/wp-block-themes/references/templates-and-parts.md +0 -0
- /package/{.github → .agents}/skills/wp-block-themes/references/theme-json.md +0 -0
- /package/{.github → .agents}/skills/wp-block-themes/scripts/detect_block_themes.mjs +0 -0
- /package/{.github → .agents}/skills/wp-interactivity-api/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-interactivity-api/references/debugging.md +0 -0
- /package/{.github → .agents}/skills/wp-interactivity-api/references/directives-quickref.md +0 -0
- /package/{.github → .agents}/skills/wp-interactivity-api/references/server-side-rendering.md +0 -0
- /package/{.github → .agents}/skills/wp-performance/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-performance/references/autoload-options.md +0 -0
- /package/{.github → .agents}/skills/wp-performance/references/cron.md +0 -0
- /package/{.github → .agents}/skills/wp-performance/references/database.md +0 -0
- /package/{.github → .agents}/skills/wp-performance/references/http-api.md +0 -0
- /package/{.github → .agents}/skills/wp-performance/references/measurement.md +0 -0
- /package/{.github → .agents}/skills/wp-performance/references/object-cache.md +0 -0
- /package/{.github → .agents}/skills/wp-performance/references/query-monitor-headless.md +0 -0
- /package/{.github → .agents}/skills/wp-performance/references/server-timing.md +0 -0
- /package/{.github → .agents}/skills/wp-performance/references/wp-cli-doctor.md +0 -0
- /package/{.github → .agents}/skills/wp-performance/references/wp-cli-profile.md +0 -0
- /package/{.github → .agents}/skills/wp-performance/scripts/perf_inspect.mjs +0 -0
- /package/{.github → .agents}/skills/wp-phpstan/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-phpstan/references/configuration.md +0 -0
- /package/{.github → .agents}/skills/wp-phpstan/references/third-party-classes.md +0 -0
- /package/{.github → .agents}/skills/wp-phpstan/references/wordpress-annotations.md +0 -0
- /package/{.github → .agents}/skills/wp-phpstan/scripts/phpstan_inspect.mjs +0 -0
- /package/{.github → .agents}/skills/wp-playground/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-playground/references/blueprints.md +0 -0
- /package/{.github → .agents}/skills/wp-playground/references/cli-commands.md +0 -0
- /package/{.github → .agents}/skills/wp-playground/references/debugging.md +0 -0
- /package/{.github → .agents}/skills/wp-playground/references/e2e-playwright.md +0 -0
- /package/{.github → .agents}/skills/wp-plugin-development/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-plugin-development/references/data-and-cron.md +0 -0
- /package/{.github → .agents}/skills/wp-plugin-development/references/debugging.md +0 -0
- /package/{.github → .agents}/skills/wp-plugin-development/references/lifecycle.md +0 -0
- /package/{.github → .agents}/skills/wp-plugin-development/references/security.md +0 -0
- /package/{.github → .agents}/skills/wp-plugin-development/references/settings-api.md +0 -0
- /package/{.github → .agents}/skills/wp-plugin-development/references/structure.md +0 -0
- /package/{.github → .agents}/skills/wp-plugin-development/scripts/detect_plugins.mjs +0 -0
- /package/{.github → .agents}/skills/wp-plugin-directory-guidelines/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-plugin-directory-guidelines/references/gpl-compliance.md +0 -0
- /package/{.github → .agents}/skills/wp-plugin-directory-guidelines/references/guideline-review-checklist.md +0 -0
- /package/{.github → .agents}/skills/wp-plugin-directory-guidelines/references/naming-rules.md +0 -0
- /package/{.github → .agents}/skills/wp-project-triage/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-project-triage/references/triage.schema.json +0 -0
- /package/{.github → .agents}/skills/wp-project-triage/scripts/detect_wp_project.mjs +0 -0
- /package/{.github → .agents}/skills/wp-rest-api/SKILL.md +0 -0
- /package/{.github → .agents}/skills/wp-rest-api/references/authentication.md +0 -0
- /package/{.github → .agents}/skills/wp-rest-api/references/custom-content-types.md +0 -0
- /package/{.github → .agents}/skills/wp-rest-api/references/discovery-and-params.md +0 -0
- /package/{.github → .agents}/skills/wp-rest-api/references/responses-and-fields.md +0 -0
- /package/{.github → .agents}/skills/wp-rest-api/references/routes-and-endpoints.md +0 -0
- /package/{.github → .agents}/skills/wp-rest-api/references/schema.md +0 -0
- /package/{.github → .agents}/skills/wp-wpcli-and-ops/references/automation.md +0 -0
- /package/{.github → .agents}/skills/wp-wpcli-and-ops/references/cron-and-cache.md +0 -0
- /package/{.github → .agents}/skills/wp-wpcli-and-ops/references/debugging.md +0 -0
- /package/{.github → .agents}/skills/wp-wpcli-and-ops/references/multisite.md +0 -0
- /package/{.github → .agents}/skills/wp-wpcli-and-ops/references/packages-and-updates.md +0 -0
- /package/{.github → .agents}/skills/wp-wpcli-and-ops/references/safety.md +0 -0
- /package/{.github → .agents}/skills/wp-wpcli-and-ops/references/search-replace.md +0 -0
- /package/{.github → .agents}/skills/wp-wpcli-and-ops/scripts/wpcli_inspect.mjs +0 -0
- /package/{.github → .agents}/skills/wpds/SKILL.md +0 -0
package/dist/lib/installer.js
CHANGED
|
@@ -12,10 +12,78 @@ export const PLATFORM_FOLDERS = {
|
|
|
12
12
|
agent: '.agent',
|
|
13
13
|
pi: '.pi/agent',
|
|
14
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* Copy universal skills from .agents/skills/ to the target directory.
|
|
17
|
+
* Uses the AgentSkills.io convention (.agents/skills/) which is discovered
|
|
18
|
+
* automatically by Pi, GitHub Copilot, and other agents.
|
|
19
|
+
*/
|
|
20
|
+
function copyUniversalSkills(targetDir) {
|
|
21
|
+
const sourceSkillsDir = path.join(PACKAGE_ROOT, '.agents', 'skills');
|
|
22
|
+
const targetSkillsDir = path.join(targetDir, '.agents', 'skills');
|
|
23
|
+
const copied = [];
|
|
24
|
+
const skipped = [];
|
|
25
|
+
if (!fs.existsSync(sourceSkillsDir)) {
|
|
26
|
+
return { copied, skipped };
|
|
27
|
+
}
|
|
28
|
+
if (!fs.existsSync(targetSkillsDir)) {
|
|
29
|
+
fs.mkdirSync(targetSkillsDir, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
for (const skillName of fs.readdirSync(sourceSkillsDir)) {
|
|
32
|
+
const src = path.join(sourceSkillsDir, skillName);
|
|
33
|
+
if (!fs.statSync(src).isDirectory())
|
|
34
|
+
continue;
|
|
35
|
+
const dest = path.join(targetSkillsDir, skillName);
|
|
36
|
+
if (fs.existsSync(dest)) {
|
|
37
|
+
skipped.push(skillName);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
fs.cpSync(src, dest, { recursive: true });
|
|
41
|
+
copied.push(skillName);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { copied, skipped };
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Merge custom skills from skills-custom/ into the target's universal skills directory.
|
|
48
|
+
* Only copies skills that don't already exist in the target (avoids overwriting
|
|
49
|
+
* upstream versions that may have been user-modified).
|
|
50
|
+
* Returns arrays of skill names that were merged or skipped.
|
|
51
|
+
*/
|
|
52
|
+
function mergeCustomSkills(targetDir) {
|
|
53
|
+
const customSkillsDir = path.join(PACKAGE_ROOT, 'skills-custom');
|
|
54
|
+
if (!fs.existsSync(customSkillsDir)) {
|
|
55
|
+
return { merged: [], skipped: [] };
|
|
56
|
+
}
|
|
57
|
+
const targetSkills = path.join(targetDir, '.agents', 'skills');
|
|
58
|
+
const merged = [];
|
|
59
|
+
const skipped = [];
|
|
60
|
+
for (const skillName of fs.readdirSync(customSkillsDir)) {
|
|
61
|
+
const src = path.join(customSkillsDir, skillName);
|
|
62
|
+
if (!fs.statSync(src).isDirectory())
|
|
63
|
+
continue;
|
|
64
|
+
const dest = path.join(targetSkills, skillName);
|
|
65
|
+
if (fs.existsSync(dest)) {
|
|
66
|
+
// Don't overwrite — upstream or user version takes priority
|
|
67
|
+
skipped.push(skillName);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
71
|
+
fs.cpSync(src, dest, { recursive: true });
|
|
72
|
+
merged.push(skillName);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { merged, skipped };
|
|
76
|
+
}
|
|
15
77
|
/**
|
|
16
78
|
* Installs the WordPress Agent Kit into the specified directory for a given platform.
|
|
17
79
|
* If the kit is already installed, uses safe update logic to preserve user modifications.
|
|
18
80
|
*
|
|
81
|
+
* Installation layout:
|
|
82
|
+
* - .agents/skills/ — Universal skills (AgentSkills.io convention)
|
|
83
|
+
* - .github/ (or .pi/agent/, etc.) — Platform-specific agents, instructions, prompts
|
|
84
|
+
* - AGENTS.md — Project-level agent instructions
|
|
85
|
+
* - AGENTS.template.md — Template reference for future updates
|
|
86
|
+
*
|
|
19
87
|
* @param targetDir - The directory where the kit should be installed.
|
|
20
88
|
* @param platform - The target platform (github, cursor, claude, agent, pi)
|
|
21
89
|
* @returns InstallKitResult with details of what was created/skipped
|
|
@@ -31,6 +99,49 @@ export function installKit(targetDir, platform = 'github', options = {}) {
|
|
|
31
99
|
// Fresh install or fallback to full replacement
|
|
32
100
|
return fullInstall(targetDir, platform, force);
|
|
33
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Migrate legacy skill directories to the universal .agents/skills/ convention.
|
|
104
|
+
* Detects skills in platform-specific directories (e.g., .github/skills/, .pi/agent/skills/)
|
|
105
|
+
* and moves them to .agents/skills/ if they don't already exist there.
|
|
106
|
+
* Returns lists of migrated and removed skill names.
|
|
107
|
+
*/
|
|
108
|
+
function migrateLegacySkills(targetDir, platform) {
|
|
109
|
+
const platformFolder = PLATFORM_FOLDERS[platform];
|
|
110
|
+
const legacySkillsDir = path.join(targetDir, platformFolder, 'skills');
|
|
111
|
+
const universalSkillsDir = path.join(targetDir, '.agents', 'skills');
|
|
112
|
+
const migrated = [];
|
|
113
|
+
const removed = [];
|
|
114
|
+
if (!fs.existsSync(legacySkillsDir)) {
|
|
115
|
+
return { migrated, removed };
|
|
116
|
+
}
|
|
117
|
+
// Ensure universal directory exists
|
|
118
|
+
if (!fs.existsSync(universalSkillsDir)) {
|
|
119
|
+
fs.mkdirSync(universalSkillsDir, { recursive: true });
|
|
120
|
+
}
|
|
121
|
+
for (const skillName of fs.readdirSync(legacySkillsDir)) {
|
|
122
|
+
const srcPath = path.join(legacySkillsDir, skillName);
|
|
123
|
+
const destPath = path.join(universalSkillsDir, skillName);
|
|
124
|
+
if (!fs.statSync(srcPath).isDirectory())
|
|
125
|
+
continue;
|
|
126
|
+
if (!fs.existsSync(destPath)) {
|
|
127
|
+
// Migrate: copy to universal location
|
|
128
|
+
fs.cpSync(srcPath, destPath, { recursive: true });
|
|
129
|
+
migrated.push(skillName);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// Already exists in universal location — just remove from legacy
|
|
133
|
+
removed.push(skillName);
|
|
134
|
+
}
|
|
135
|
+
// Remove from legacy location
|
|
136
|
+
fs.rmSync(srcPath, { recursive: true, force: true });
|
|
137
|
+
}
|
|
138
|
+
// Remove the legacy skills directory if empty
|
|
139
|
+
const remaining = fs.readdirSync(legacySkillsDir);
|
|
140
|
+
if (remaining.length === 0) {
|
|
141
|
+
fs.rmSync(legacySkillsDir, { recursive: true, force: true });
|
|
142
|
+
}
|
|
143
|
+
return { migrated, removed };
|
|
144
|
+
}
|
|
34
145
|
/**
|
|
35
146
|
* Check if kit is already installed for a platform.
|
|
36
147
|
*/
|
|
@@ -53,18 +164,23 @@ function fullInstall(targetDir, platform, _force) {
|
|
|
53
164
|
const sourceGithub = path.join(PACKAGE_ROOT, '.github');
|
|
54
165
|
const filesCreated = [];
|
|
55
166
|
const filesSkipped = [];
|
|
56
|
-
// Copy platform-specific folder
|
|
167
|
+
// Copy platform-specific folder (agents, instructions — NOT skills)
|
|
57
168
|
const targetPlatform = path.join(targetDir, platformFolder);
|
|
58
169
|
if (fs.existsSync(targetPlatform)) {
|
|
59
170
|
fs.rmSync(targetPlatform, { recursive: true, force: true });
|
|
60
171
|
}
|
|
61
172
|
if (fs.existsSync(sourceGithub)) {
|
|
62
173
|
fs.cpSync(sourceGithub, targetPlatform, { recursive: true });
|
|
174
|
+
// Remove skills from platform dir — skills go to .agents/skills/ instead
|
|
175
|
+
const platformSkills = path.join(targetPlatform, 'skills');
|
|
176
|
+
if (fs.existsSync(platformSkills)) {
|
|
177
|
+
fs.rmSync(platformSkills, { recursive: true, force: true });
|
|
178
|
+
}
|
|
63
179
|
}
|
|
64
180
|
else {
|
|
65
181
|
throw new Error('Could not find source .github directory.');
|
|
66
182
|
}
|
|
67
|
-
// Collect created files
|
|
183
|
+
// Collect created files (excluding skills which are in .agents/)
|
|
68
184
|
const collectFiles = (dir, prefix) => {
|
|
69
185
|
if (!fs.existsSync(dir))
|
|
70
186
|
return;
|
|
@@ -81,6 +197,30 @@ function fullInstall(targetDir, platform, _force) {
|
|
|
81
197
|
}
|
|
82
198
|
};
|
|
83
199
|
collectFiles(targetPlatform, platformFolder);
|
|
200
|
+
// Migrate legacy skills from platform-specific dir to .agents/skills/
|
|
201
|
+
const migrationResult = migrateLegacySkills(targetDir, platform);
|
|
202
|
+
for (const skill of migrationResult.migrated) {
|
|
203
|
+
filesCreated.push(`.agents/skills/${skill} (migrated from ${platformFolder}/skills/)`);
|
|
204
|
+
}
|
|
205
|
+
for (const skill of migrationResult.removed) {
|
|
206
|
+
filesSkipped.push(`.agents/skills/${skill} (already existed, removed legacy copy)`);
|
|
207
|
+
}
|
|
208
|
+
// Copy universal skills to .agents/skills/ (AgentSkills.io convention)
|
|
209
|
+
const universalResult = copyUniversalSkills(targetDir);
|
|
210
|
+
for (const skill of universalResult.copied) {
|
|
211
|
+
filesCreated.push(`.agents/skills/${skill}`);
|
|
212
|
+
}
|
|
213
|
+
for (const skill of universalResult.skipped) {
|
|
214
|
+
filesSkipped.push(`.agents/skills/${skill} (already exists, preserved)`);
|
|
215
|
+
}
|
|
216
|
+
// Merge custom skills from skills-custom/ (e.g., wp-wpengine)
|
|
217
|
+
const customResult = mergeCustomSkills(targetDir);
|
|
218
|
+
for (const skill of customResult.merged) {
|
|
219
|
+
filesCreated.push(`.agents/skills/${skill}`);
|
|
220
|
+
}
|
|
221
|
+
for (const skill of customResult.skipped) {
|
|
222
|
+
filesSkipped.push(`.agents/skills/${skill} (already exists, preserved)`);
|
|
223
|
+
}
|
|
84
224
|
// Copy AGENTS.md template
|
|
85
225
|
const targetAgentsTemplate = path.join(targetDir, 'AGENTS.template.md');
|
|
86
226
|
if (fs.existsSync(templatePath)) {
|
|
@@ -140,6 +280,30 @@ function safeUpdateInstall(targetDir, platform, options) {
|
|
|
140
280
|
else {
|
|
141
281
|
filesSkipped.push('AGENTS.md (preserved)');
|
|
142
282
|
}
|
|
283
|
+
// Migrate legacy skills from platform-specific dir to .agents/skills/
|
|
284
|
+
const migrationResult = migrateLegacySkills(targetDir, platform);
|
|
285
|
+
for (const skill of migrationResult.migrated) {
|
|
286
|
+
filesCreated.push(`.agents/skills/${skill} (migrated from ${PLATFORM_FOLDERS[platform]}/skills/)`);
|
|
287
|
+
}
|
|
288
|
+
for (const skill of migrationResult.removed) {
|
|
289
|
+
filesSkipped.push(`.agents/skills/${skill} (already existed, removed legacy copy)`);
|
|
290
|
+
}
|
|
291
|
+
// Copy universal skills to .agents/skills/ (AgentSkills.io convention)
|
|
292
|
+
const universalResult = copyUniversalSkills(targetDir);
|
|
293
|
+
for (const skill of universalResult.copied) {
|
|
294
|
+
filesCreated.push(`.agents/skills/${skill}`);
|
|
295
|
+
}
|
|
296
|
+
for (const skill of universalResult.skipped) {
|
|
297
|
+
filesSkipped.push(`.agents/skills/${skill} (already exists, preserved)`);
|
|
298
|
+
}
|
|
299
|
+
// Merge custom skills from skills-custom/ (e.g., wp-wpengine)
|
|
300
|
+
const customResult = mergeCustomSkills(targetDir);
|
|
301
|
+
for (const skill of customResult.merged) {
|
|
302
|
+
filesCreated.push(`.agents/skills/${skill}`);
|
|
303
|
+
}
|
|
304
|
+
for (const skill of customResult.skipped) {
|
|
305
|
+
filesSkipped.push(`.agents/skills/${skill} (already exists, preserved)`);
|
|
306
|
+
}
|
|
143
307
|
return {
|
|
144
308
|
targetDir,
|
|
145
309
|
platform,
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
1
2
|
import path from 'node:path';
|
|
2
3
|
import { fileURLToPath } from 'node:url';
|
|
3
4
|
/**
|
|
4
5
|
* WordPress Agent Kit — Pi Extension
|
|
5
6
|
*
|
|
6
7
|
* Provides Pi Coding Agent with WordPress development tools:
|
|
7
|
-
* -
|
|
8
|
+
* - 18 WordPress agent skills (17 upstream + wp-wpengine custom) at .agents/skills/ (AgentSkills.io convention)
|
|
8
9
|
* - Project triage detection
|
|
9
|
-
* - Skill installation, syncing, and
|
|
10
|
+
* - Skill installation, syncing, upgrade, orphan cleanup, and project bootstrapping
|
|
10
11
|
*
|
|
11
12
|
* Follows Pi Coding Agent SDK conventions (extensions.md, packages.md, skills.md).
|
|
12
13
|
*/
|
|
@@ -25,17 +26,50 @@ try {
|
|
|
25
26
|
apiModule = (await import('../../src/lib/api.js')) as typeof import('../../dist/lib/api.js');
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
const {
|
|
29
|
+
const {
|
|
30
|
+
installKitApi,
|
|
31
|
+
syncSkillsApi,
|
|
32
|
+
runTriageApi,
|
|
33
|
+
cleanSkillsApi,
|
|
34
|
+
bootstrapApi,
|
|
35
|
+
isKitInstalled,
|
|
36
|
+
loadManifest,
|
|
37
|
+
} = apiModule;
|
|
29
38
|
|
|
30
39
|
export default function (pi: ExtensionAPI) {
|
|
31
40
|
// =========================================================================
|
|
32
41
|
// Skills Registration
|
|
33
42
|
// =========================================================================
|
|
43
|
+
// Primary skills (.agents/skills/) are registered via `pi.skills` in package.json.
|
|
44
|
+
// Pi also auto-discovers from .agents/skills/ at the project level (AgentSkills.io convention).
|
|
45
|
+
// The resources_discover handler ONLY supplements skills that aren't already
|
|
46
|
+
// covered by the static manifest — specifically, custom skills from
|
|
47
|
+
// skills-custom/ that haven't been synced into .agents/skills/ yet.
|
|
48
|
+
// This avoids name collisions (Pi keeps first-loaded, warns on duplicates).
|
|
34
49
|
pi.on('resources_discover', async (_event, _ctx) => {
|
|
35
|
-
const
|
|
50
|
+
const canonicalSkillsDir = path.join(PACKAGE_ROOT, '.agents', 'skills');
|
|
51
|
+
const customSkillsDir = path.join(PACKAGE_ROOT, 'skills-custom');
|
|
36
52
|
const promptsDir = path.join(PACKAGE_ROOT, '.github', 'prompts');
|
|
53
|
+
|
|
54
|
+
// Only discover custom skills that aren't already in .agents/skills/
|
|
55
|
+
// (which is registered via pi.skills in package.json).
|
|
56
|
+
const skillPaths: string[] = [];
|
|
57
|
+
if (fs.existsSync(customSkillsDir)) {
|
|
58
|
+
const existingSkills = fs.existsSync(canonicalSkillsDir)
|
|
59
|
+
? new Set(fs.readdirSync(canonicalSkillsDir))
|
|
60
|
+
: new Set<string>();
|
|
61
|
+
for (const entry of fs.readdirSync(customSkillsDir)) {
|
|
62
|
+
if (!existingSkills.has(entry)) {
|
|
63
|
+
const entryPath = path.join(customSkillsDir, entry);
|
|
64
|
+
if (fs.statSync(entryPath).isDirectory()) {
|
|
65
|
+
skillPaths.push(entryPath);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
37
71
|
return {
|
|
38
|
-
skillPaths:
|
|
72
|
+
skillPaths: skillPaths.length > 0 ? skillPaths : undefined,
|
|
39
73
|
promptPaths: [promptsDir],
|
|
40
74
|
};
|
|
41
75
|
});
|
|
@@ -127,7 +161,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
127
161
|
name: 'wp_install_kit',
|
|
128
162
|
label: 'WP Install Kit',
|
|
129
163
|
description:
|
|
130
|
-
'Install WordPress Agent Kit into a project directory. Copies
|
|
164
|
+
'Install WordPress Agent Kit into a project directory. Copies 18 WordPress skills to .agents/skills/ (AgentSkills.io convention), platform-specific agents/instructions/prompts, and an AGENTS.md template. Safe by default — preserves user modifications on re-run.',
|
|
131
165
|
promptSnippet: 'Install WordPress AI agent skills and configuration into a project',
|
|
132
166
|
promptGuidelines: [
|
|
133
167
|
'Use wp_install_kit when setting up a new WordPress project for AI agent development.',
|
|
@@ -243,7 +277,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
243
277
|
name: 'wp_sync_skills',
|
|
244
278
|
label: 'WP Sync Skills',
|
|
245
279
|
description:
|
|
246
|
-
'Sync WordPress agent skills from the upstream WordPress/agent-skills repository. Fetches the latest
|
|
280
|
+
'Sync WordPress agent skills from the upstream WordPress/agent-skills repository. Fetches the latest upstream skill definitions and merges custom skills from skills-custom/ — custom skills survive upstream syncs.',
|
|
247
281
|
promptSnippet: 'Sync latest WordPress agent skills from upstream',
|
|
248
282
|
promptGuidelines: [
|
|
249
283
|
'Use wp_sync_skills to pull the latest WordPress development skills from WordPress/agent-skills.',
|
|
@@ -273,11 +307,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
273
307
|
}
|
|
274
308
|
|
|
275
309
|
const data = result.data as { skillsSynced: number; method: string };
|
|
310
|
+
const customSkillNote = fs.existsSync(path.join(PACKAGE_ROOT, 'skills-custom'))
|
|
311
|
+
? '\n**Custom skills**: Merged from skills-custom/'
|
|
312
|
+
: '';
|
|
276
313
|
return {
|
|
277
314
|
content: [
|
|
278
315
|
{
|
|
279
316
|
type: 'text',
|
|
280
|
-
text: `# Skills Synced\n\n**Synced**: ${data.skillsSynced} skills\n**Method**: ${data.method}`,
|
|
317
|
+
text: `# Skills Synced\n\n**Synced**: ${data.skillsSynced} skills\n**Method**: ${data.method}${customSkillNote}`,
|
|
281
318
|
},
|
|
282
319
|
],
|
|
283
320
|
details: data,
|
|
@@ -315,7 +352,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
315
352
|
const currentVersion = manifest?.version || 'not installed';
|
|
316
353
|
const latestVersion = (() => {
|
|
317
354
|
try {
|
|
318
|
-
const fs = require('node:fs');
|
|
319
355
|
return JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf-8'))
|
|
320
356
|
.version;
|
|
321
357
|
} catch {
|
|
@@ -393,6 +429,221 @@ export default function (pi: ExtensionAPI) {
|
|
|
393
429
|
},
|
|
394
430
|
});
|
|
395
431
|
|
|
432
|
+
// --- wp_clean_skills ---
|
|
433
|
+
pi.registerTool({
|
|
434
|
+
name: 'wp_clean_skills',
|
|
435
|
+
label: 'WP Clean Skills',
|
|
436
|
+
description:
|
|
437
|
+
'Detect and remove orphaned skills from a WordPress Agent Kit installation. Compares installed skills against the canonical set (upstream + custom) and reports or removes skills that are no longer part of the kit. Safe by default — use dryRun first to preview.',
|
|
438
|
+
promptSnippet: 'Clean up orphaned WordPress agent skills',
|
|
439
|
+
promptGuidelines: [
|
|
440
|
+
'Use wp_clean_skills after upgrading to remove skills that are no longer part of the kit.',
|
|
441
|
+
'Always run with dryRun: true first to preview what would be removed.',
|
|
442
|
+
'This only removes skill directories — it does not modify AGENTS.md or other config files.',
|
|
443
|
+
],
|
|
444
|
+
parameters: Type.Object({
|
|
445
|
+
targetDir: Type.Optional(
|
|
446
|
+
Type.String({
|
|
447
|
+
description: 'WordPress project directory (defaults to current working directory)',
|
|
448
|
+
})
|
|
449
|
+
),
|
|
450
|
+
dryRun: Type.Optional(
|
|
451
|
+
Type.Boolean({
|
|
452
|
+
description: 'Preview changes without applying (default: true for safety)',
|
|
453
|
+
})
|
|
454
|
+
),
|
|
455
|
+
remove: Type.Optional(
|
|
456
|
+
Type.Boolean({
|
|
457
|
+
description: 'Actually remove orphaned skills (default: false — report only)',
|
|
458
|
+
})
|
|
459
|
+
),
|
|
460
|
+
}),
|
|
461
|
+
async execute(_callId, params, _signal, _onUpdate, _ctx) {
|
|
462
|
+
const targetDir = params.targetDir || process.cwd();
|
|
463
|
+
const dryRun = params.dryRun ?? true;
|
|
464
|
+
const remove = params.remove ?? false;
|
|
465
|
+
|
|
466
|
+
const result = await cleanSkillsApi({
|
|
467
|
+
targetDir,
|
|
468
|
+
platform: 'pi',
|
|
469
|
+
dryRun,
|
|
470
|
+
remove,
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
if (!result.success) {
|
|
474
|
+
return {
|
|
475
|
+
content: [
|
|
476
|
+
{ type: 'text', text: `Clean failed: ${result.error?.message || 'Unknown error'}` },
|
|
477
|
+
],
|
|
478
|
+
isError: true,
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const data = result.data as {
|
|
483
|
+
orphanedSkills: string[];
|
|
484
|
+
removedSkills: string[];
|
|
485
|
+
legacySkillDirs: string[];
|
|
486
|
+
migratedSkills: string[];
|
|
487
|
+
dryRun: boolean;
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
const hasNoIssues = data.orphanedSkills.length === 0 && data.legacySkillDirs.length === 0;
|
|
491
|
+
if (hasNoIssues) {
|
|
492
|
+
return {
|
|
493
|
+
content: [
|
|
494
|
+
{
|
|
495
|
+
type: 'text',
|
|
496
|
+
text: '# All Clean\n\nAll installed skills match the canonical set. No orphaned or legacy skills found.',
|
|
497
|
+
},
|
|
498
|
+
],
|
|
499
|
+
details: data,
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const lines = [dryRun ? '# Skills Cleanup Preview (Dry Run)' : '# Skills Cleaned Up', ''];
|
|
504
|
+
|
|
505
|
+
if (data.orphanedSkills.length > 0) {
|
|
506
|
+
lines.push(`**Orphaned skills** (${data.orphanedSkills.length}):`);
|
|
507
|
+
for (const skill of data.orphanedSkills) {
|
|
508
|
+
lines.push(`- ${skill}`);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (data.legacySkillDirs.length > 0) {
|
|
513
|
+
lines.push('', `**Legacy skill directories** (${data.legacySkillDirs.length}):`);
|
|
514
|
+
for (const dir of data.legacySkillDirs) {
|
|
515
|
+
lines.push(`- ${dir}`);
|
|
516
|
+
}
|
|
517
|
+
lines.push('These will be migrated to `.agents/skills/` and then removed.');
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
if (dryRun) {
|
|
521
|
+
lines.push('', 'Run with `remove: true` to clean up.');
|
|
522
|
+
} else {
|
|
523
|
+
if (data.removedSkills.length > 0) {
|
|
524
|
+
lines.push('', `Removed **${data.removedSkills.length}** orphaned skill(s).`);
|
|
525
|
+
}
|
|
526
|
+
if (data.migratedSkills.length > 0) {
|
|
527
|
+
lines.push(
|
|
528
|
+
`Migrated **${data.migratedSkills.length}** skill(s) from legacy directories.`
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return {
|
|
534
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
535
|
+
details: data,
|
|
536
|
+
};
|
|
537
|
+
},
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
// --- wp_bootstrap ---
|
|
541
|
+
pi.registerTool({
|
|
542
|
+
name: 'wp_bootstrap',
|
|
543
|
+
label: 'WP Bootstrap',
|
|
544
|
+
description:
|
|
545
|
+
'Bootstrap a WordPress project: detect monorepo structure, install agent kit, scaffold Composer/WPackagist/SatisPress, WP-CLI aliases, git hooks, Playground scripts, and WP Engine CI/CD. Supports single plugins/themes and monorepos (multiple WP packages + JS workspaces).',
|
|
546
|
+
promptSnippet: 'Detect WordPress project structure and bootstrap full tooling',
|
|
547
|
+
promptGuidelines: [
|
|
548
|
+
'Always run wp_bootstrap with detectOnly: true first to understand the project structure.',
|
|
549
|
+
'Use the structure report to identify monorepo patterns before scaffolding.',
|
|
550
|
+
'For monorepos, confirm WP package paths before proceeding.',
|
|
551
|
+
],
|
|
552
|
+
parameters: Type.Object({
|
|
553
|
+
targetDir: Type.Optional(
|
|
554
|
+
Type.String({
|
|
555
|
+
description: 'Project root directory (defaults to current working directory)',
|
|
556
|
+
})
|
|
557
|
+
),
|
|
558
|
+
detectOnly: Type.Optional(
|
|
559
|
+
Type.Boolean({
|
|
560
|
+
description: 'Only detect structure, do not scaffold anything (default: false)',
|
|
561
|
+
})
|
|
562
|
+
),
|
|
563
|
+
platform: Type.Optional(
|
|
564
|
+
Type.String({
|
|
565
|
+
description: 'Agent kit platform: github, pi, cursor, claude (default: github)',
|
|
566
|
+
})
|
|
567
|
+
),
|
|
568
|
+
wpeProd: Type.Optional(Type.String({ description: 'WP Engine production install slug' })),
|
|
569
|
+
wpeStaging: Type.Optional(Type.String({ description: 'WP Engine staging install slug' })),
|
|
570
|
+
wpeDev: Type.Optional(Type.String({ description: 'WP Engine development install slug' })),
|
|
571
|
+
withWpackagist: Type.Optional(
|
|
572
|
+
Type.Boolean({ description: 'Add WPackagist to composer.json' })
|
|
573
|
+
),
|
|
574
|
+
withSatispress: Type.Optional(
|
|
575
|
+
Type.String({ description: 'SatisPress URL to add to composer.json' })
|
|
576
|
+
),
|
|
577
|
+
dryRun: Type.Optional(
|
|
578
|
+
Type.Boolean({ description: 'Preview without making changes (default: false)' })
|
|
579
|
+
),
|
|
580
|
+
}),
|
|
581
|
+
async execute(_callId, params, _signal, onUpdate, _ctx) {
|
|
582
|
+
const targetDir = params.targetDir || process.cwd();
|
|
583
|
+
|
|
584
|
+
onUpdate?.({ content: [{ type: 'text', text: '▶ Detecting project structure...' }] });
|
|
585
|
+
|
|
586
|
+
const result = await bootstrapApi({
|
|
587
|
+
targetDir,
|
|
588
|
+
platform: (params.platform as 'github' | 'pi' | 'cursor' | 'claude') ?? 'github',
|
|
589
|
+
detectOnly: params.detectOnly ?? false,
|
|
590
|
+
dryRun: params.dryRun ?? false,
|
|
591
|
+
wpeEnvironments: {
|
|
592
|
+
production: params.wpeProd,
|
|
593
|
+
staging: params.wpeStaging,
|
|
594
|
+
development: params.wpeDev,
|
|
595
|
+
},
|
|
596
|
+
withWpackagist: params.withWpackagist,
|
|
597
|
+
withSatispress: params.withSatispress,
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
if (!result.success) {
|
|
601
|
+
return {
|
|
602
|
+
content: [
|
|
603
|
+
{ type: 'text', text: `Bootstrap failed: ${result.error?.message || 'Unknown error'}` },
|
|
604
|
+
],
|
|
605
|
+
isError: true,
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
const data = result.data as {
|
|
610
|
+
detectOnly: boolean;
|
|
611
|
+
structure: {
|
|
612
|
+
isMonorepo: boolean;
|
|
613
|
+
wpPackages: Array<{ type: string; name: string; path: string }>;
|
|
614
|
+
wpRoot: string | null;
|
|
615
|
+
packageManager: string;
|
|
616
|
+
wpeRemotes: Array<{ name: string; install: string }>;
|
|
617
|
+
};
|
|
618
|
+
actions: string[];
|
|
619
|
+
filesCreated: string[];
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
if (data.detectOnly) {
|
|
623
|
+
const s = data.structure;
|
|
624
|
+
const lines = [
|
|
625
|
+
'# Project Structure',
|
|
626
|
+
'',
|
|
627
|
+
`**Monorepo**: ${s.isMonorepo ? 'yes' : 'no'} | **Package manager**: ${s.packageManager ?? 'none'} | **WP root**: ${s.wpRoot ?? 'Playground-only'}`,
|
|
628
|
+
'',
|
|
629
|
+
`**WP packages** (${s.wpPackages.length}):`,
|
|
630
|
+
...s.wpPackages.map(
|
|
631
|
+
(p) => `- ${p.type === 'plugin' ? '🔌' : '🎨'} ${p.name ?? p.path} (\`${p.path}\`)`
|
|
632
|
+
),
|
|
633
|
+
'',
|
|
634
|
+
`**WP Engine remotes** (${s.wpeRemotes.length}):`,
|
|
635
|
+
...s.wpeRemotes.map((r) => `- ${r.name} (${r.install})`),
|
|
636
|
+
];
|
|
637
|
+
return { content: [{ type: 'text', text: lines.join('\n') }], details: data.structure };
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
return {
|
|
641
|
+
content: [{ type: 'text', text: ['# Bootstrap Complete', '', ...data.actions].join('\n') }],
|
|
642
|
+
details: data,
|
|
643
|
+
};
|
|
644
|
+
},
|
|
645
|
+
});
|
|
646
|
+
|
|
396
647
|
// =========================================================================
|
|
397
648
|
// Commands
|
|
398
649
|
// =========================================================================
|
|
@@ -431,7 +682,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
431
682
|
`${data.isUpdate ? 'Updated' : 'Installed'} (${data.filesCreated.length} entries)`,
|
|
432
683
|
'info'
|
|
433
684
|
);
|
|
434
|
-
|
|
685
|
+
const pkgVersion = (() => {
|
|
686
|
+
try {
|
|
687
|
+
return JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf-8'))
|
|
688
|
+
.version;
|
|
689
|
+
} catch {
|
|
690
|
+
return 'unknown';
|
|
691
|
+
}
|
|
692
|
+
})();
|
|
693
|
+
ctx.ui.setStatus('wp-agent-kit', `v${pkgVersion} installed`);
|
|
435
694
|
},
|
|
436
695
|
});
|
|
437
696
|
|
|
@@ -449,4 +708,60 @@ export default function (pi: ExtensionAPI) {
|
|
|
449
708
|
ctx.ui.setStatus('wp-agent-kit', `${data.skillsSynced} skills`);
|
|
450
709
|
},
|
|
451
710
|
});
|
|
711
|
+
|
|
712
|
+
pi.registerCommand('wp-clean-skills', {
|
|
713
|
+
description: 'Detect and remove orphaned/legacy skills from WordPress Agent Kit',
|
|
714
|
+
handler: async (args, ctx) => {
|
|
715
|
+
const targetDir = args?.trim() || ctx.cwd;
|
|
716
|
+
ctx.ui.setStatus('wp-clean', 'Checking for orphaned and legacy skills...');
|
|
717
|
+
const result = await cleanSkillsApi({
|
|
718
|
+
targetDir,
|
|
719
|
+
platform: 'pi',
|
|
720
|
+
dryRun: true,
|
|
721
|
+
remove: false,
|
|
722
|
+
});
|
|
723
|
+
if (!result.success) {
|
|
724
|
+
ctx.ui.notify(`Clean failed: ${result.error?.message}`, 'error');
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
const data = result.data as { orphanedSkills: string[]; legacySkillDirs: string[] };
|
|
728
|
+
const total = data.orphanedSkills.length + data.legacySkillDirs.length;
|
|
729
|
+
if (total === 0) {
|
|
730
|
+
ctx.ui.notify('No orphaned or legacy skills found', 'info');
|
|
731
|
+
} else {
|
|
732
|
+
const parts: string[] = [];
|
|
733
|
+
if (data.orphanedSkills.length > 0) parts.push(`${data.orphanedSkills.length} orphaned`);
|
|
734
|
+
if (data.legacySkillDirs.length > 0)
|
|
735
|
+
parts.push(`${data.legacySkillDirs.length} legacy dir(s)`);
|
|
736
|
+
ctx.ui.notify(`Found ${parts.join(', ')}`, 'info');
|
|
737
|
+
}
|
|
738
|
+
ctx.ui.setStatus('wp-clean', total === 0 ? 'clean' : `${total} issues`);
|
|
739
|
+
},
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
pi.registerCommand('wp-bootstrap', {
|
|
743
|
+
description: 'Detect WordPress project structure and bootstrap the full toolkit',
|
|
744
|
+
handler: async (args, ctx) => {
|
|
745
|
+
const targetDir = args?.trim() || ctx.cwd;
|
|
746
|
+
ctx.ui.setStatus('wp-bootstrap', 'Detecting...');
|
|
747
|
+
const result = await bootstrapApi({ targetDir, detectOnly: true });
|
|
748
|
+
if (!result.success) {
|
|
749
|
+
ctx.ui.notify(`Bootstrap failed: ${result.error?.message}`, 'error');
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
const data = result.data as {
|
|
753
|
+
structure: {
|
|
754
|
+
isMonorepo: boolean;
|
|
755
|
+
wpPackages: Array<{ type: string; name: string; path: string }>;
|
|
756
|
+
};
|
|
757
|
+
};
|
|
758
|
+
const s = data.structure;
|
|
759
|
+
const pkgCount = s.wpPackages.length;
|
|
760
|
+
const label = s.isMonorepo
|
|
761
|
+
? `monorepo (${pkgCount} packages)`
|
|
762
|
+
: `${s.wpPackages[0]?.type ?? 'unknown'} (${pkgCount} package)`;
|
|
763
|
+
ctx.ui.notify(`Detected: ${label}`, 'info');
|
|
764
|
+
ctx.ui.setStatus('wp-bootstrap', label);
|
|
765
|
+
},
|
|
766
|
+
});
|
|
452
767
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wordpress-agent-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "WordPress-focused AGENTS.md + Agent Skills starter kit for AI coding agents.",
|
|
5
5
|
"license": "GPL-2.0-or-later",
|
|
6
6
|
"author": "Kyle Brodeur <kyle@brodeur.me> (https://brodeur.me)",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"./extensions/wp-agent-kit"
|
|
32
32
|
],
|
|
33
33
|
"skills": [
|
|
34
|
-
"./.
|
|
34
|
+
"./.agents/skills"
|
|
35
35
|
]
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
@@ -44,28 +44,20 @@
|
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@biomejs/biome": "1.9.4",
|
|
47
|
-
"@
|
|
47
|
+
"@earendil-works/pi-coding-agent": "^0.78.1",
|
|
48
48
|
"@types/node": "^22.10.1",
|
|
49
49
|
"@vitest/coverage-v8": "^2.1.8",
|
|
50
|
-
"eslint": "^9.16.0",
|
|
51
50
|
"husky": "^9.1.6",
|
|
52
|
-
"prettier": "^3.4.1",
|
|
53
51
|
"ts-node": "^10.9.2",
|
|
54
52
|
"tsx": "^4.19.2",
|
|
53
|
+
"typebox": "*",
|
|
55
54
|
"typescript": "^5.7.2",
|
|
56
|
-
"
|
|
57
|
-
"vitest": "^2.1.8",
|
|
58
|
-
"@earendil-works/pi-coding-agent": "^0.78.1",
|
|
59
|
-
"typebox": "*"
|
|
55
|
+
"vitest": "^2.1.8"
|
|
60
56
|
},
|
|
61
57
|
"scripts": {
|
|
62
58
|
"dev": "tsx src/cli.ts",
|
|
63
59
|
"build": "tsc",
|
|
64
60
|
"check": "tsc --noEmit",
|
|
65
|
-
"lint": "eslint src/ tests/ --fix && biome check --write .",
|
|
66
|
-
"lint:check": "eslint src/ tests/ && biome check .",
|
|
67
|
-
"format": "prettier --write . && biome format --write .",
|
|
68
|
-
"format:check": "prettier --check . && biome format --check .",
|
|
69
61
|
"test": "vitest",
|
|
70
62
|
"test:run": "vitest run",
|
|
71
63
|
"test:coverage": "vitest run --coverage",
|
|
@@ -73,6 +65,10 @@
|
|
|
73
65
|
"sync:skills": "tsx src/cli.ts sync-skills",
|
|
74
66
|
"setup": "tsx src/cli.ts setup",
|
|
75
67
|
"playground": "tsx src/cli.ts playground",
|
|
76
|
-
"build:bundles": "tsx scripts/build-bundles.ts"
|
|
68
|
+
"build:bundles": "tsx scripts/build-bundles.ts",
|
|
69
|
+
"lint": "biome check --write .",
|
|
70
|
+
"lint:check": "biome check .",
|
|
71
|
+
"format": "biome format --write .",
|
|
72
|
+
"format:check": "biome format --check ."
|
|
77
73
|
}
|
|
78
74
|
}
|