@sadrmanesh/commerce-agent-skills 0.0.0-stage → 0.3.1
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/CHANGELOG.md +53 -0
- package/LICENSE +21 -0
- package/README.md +143 -2
- package/bin/commerce-agent-skills.mjs +368 -0
- package/package.json +52 -4
- package/rules/b2b-pricing.md +11 -0
- package/rules/catalog-import-and-migration.md +11 -0
- package/rules/checkout-ux-and-conversion.md +12 -0
- package/rules/conversion-event-tracking.md +11 -0
- package/rules/ecommerce-seo-structured-data.md +11 -0
- package/rules/fraud-and-risk-basics.md +11 -0
- package/rules/google-merchant-product-feeds.md +11 -0
- package/rules/headless-nextjs-storefront.md +10 -0
- package/rules/inventory-and-multi-warehouse.md +10 -0
- package/rules/iranian-payment-gateways.md +10 -0
- package/rules/marketplace-search-and-ranking.md +10 -0
- package/rules/mcp-store-tooling.md +11 -0
- package/rules/multi-vendor-payouts.md +11 -0
- package/rules/order-and-webhook-reliability.md +12 -0
- package/rules/payment-gateway-integration.md +12 -0
- package/rules/product-catalog-modeling.md +11 -0
- package/rules/product-description-guardrails.md +10 -0
- package/rules/returns-and-refunds.md +10 -0
- package/rules/rtl-and-persian-localization.md +11 -0
- package/rules/shopify-app-development.md +10 -0
- package/rules/storefront-accessibility.md +11 -0
- package/rules/storefront-performance.md +10 -0
- package/rules/stripe-payments.md +10 -0
- package/rules/subscription-billing.md +10 -0
- package/rules/tax-and-shipping.md +10 -0
- package/rules/vector-product-search.md +10 -0
- package/rules/woocommerce-plugin-development.md +10 -0
- package/rules/woocommerce-rest-api.md +10 -0
- package/rules/wordpress-plugin-security.md +10 -0
- package/scripts/lib/frontmatter.mjs +218 -0
- package/skills/b2b-pricing/SKILL.md +55 -0
- package/skills/b2b-pricing/evals/examples/net-terms.md +3 -0
- package/skills/b2b-pricing/evals/examples/tiered-wholesale.md +3 -0
- package/skills/b2b-pricing/evals/tasks.json +19 -0
- package/skills/b2b-pricing/references/price-lists.md +46 -0
- package/skills/b2b-pricing/scripts/resolve-price.mjs +93 -0
- package/skills/catalog-import-and-migration/SKILL.md +58 -0
- package/skills/catalog-import-and-migration/evals/examples/platform-migration-urls.md +3 -0
- package/skills/catalog-import-and-migration/evals/examples/rerunnable-import.md +3 -0
- package/skills/catalog-import-and-migration/evals/tasks.json +20 -0
- package/skills/catalog-import-and-migration/references/field-mapping.md +43 -0
- package/skills/catalog-import-and-migration/scripts/check-import-rows.mjs +75 -0
- package/skills/catalog-order.txt +29 -0
- package/skills/checkout-ux-and-conversion/SKILL.md +86 -0
- package/skills/checkout-ux-and-conversion/evals/examples/guest-total.md +3 -0
- package/skills/checkout-ux-and-conversion/evals/examples/single-submit.md +3 -0
- package/skills/checkout-ux-and-conversion/evals/tasks.json +30 -0
- package/skills/checkout-ux-and-conversion/references/checkout-review.md +41 -0
- package/skills/conversion-event-tracking/SKILL.md +64 -0
- package/skills/conversion-event-tracking/evals/examples/purchase-once.md +3 -0
- package/skills/conversion-event-tracking/evals/examples/variant-item-id.md +3 -0
- package/skills/conversion-event-tracking/evals/tasks.json +30 -0
- package/skills/conversion-event-tracking/references/events.md +36 -0
- package/skills/conversion-event-tracking/scripts/check-event.mjs +79 -0
- package/skills/ecommerce-seo-structured-data/SKILL.md +84 -0
- package/skills/ecommerce-seo-structured-data/assets/example-product.jsonld +15 -0
- package/skills/ecommerce-seo-structured-data/evals/examples/extend-woocommerce-schema.md +8 -0
- package/skills/ecommerce-seo-structured-data/evals/examples/variant-offer.md +7 -0
- package/skills/ecommerce-seo-structured-data/evals/tasks.json +29 -0
- package/skills/ecommerce-seo-structured-data/references/product-jsonld.md +83 -0
- package/skills/ecommerce-seo-structured-data/scripts/check-product-jsonld.mjs +211 -0
- package/skills/fraud-and-risk-basics/SKILL.md +66 -0
- package/skills/fraud-and-risk-basics/evals/examples/review-queue.md +3 -0
- package/skills/fraud-and-risk-basics/evals/examples/wait-for-3ds.md +3 -0
- package/skills/fraud-and-risk-basics/evals/tasks.json +30 -0
- package/skills/google-merchant-product-feeds/SKILL.md +70 -0
- package/skills/google-merchant-product-feeds/assets/example-item.json +11 -0
- package/skills/google-merchant-product-feeds/evals/examples/generated-title.md +3 -0
- package/skills/google-merchant-product-feeds/evals/examples/stable-variant-id.md +3 -0
- package/skills/google-merchant-product-feeds/evals/tasks.json +30 -0
- package/skills/google-merchant-product-feeds/references/attributes.md +39 -0
- package/skills/google-merchant-product-feeds/scripts/check-feed-item.mjs +92 -0
- package/skills/headless-nextjs-storefront/SKILL.md +69 -0
- package/skills/headless-nextjs-storefront/evals/examples/revalidate-stock.md +7 -0
- package/skills/headless-nextjs-storefront/evals/examples/server-price.md +3 -0
- package/skills/headless-nextjs-storefront/evals/tasks.json +30 -0
- package/skills/headless-nextjs-storefront/references/cache-and-cart.md +39 -0
- package/skills/inventory-and-multi-warehouse/SKILL.md +61 -0
- package/skills/inventory-and-multi-warehouse/evals/examples/reserve-last-unit.md +3 -0
- package/skills/inventory-and-multi-warehouse/evals/examples/split-order.md +3 -0
- package/skills/inventory-and-multi-warehouse/evals/tasks.json +20 -0
- package/skills/inventory-and-multi-warehouse/references/platforms.md +40 -0
- package/skills/inventory-and-multi-warehouse/scripts/allocate-stock.mjs +72 -0
- package/skills/iranian-payment-gateways/SKILL.md +64 -0
- package/skills/iranian-payment-gateways/evals/examples/toman-store.md +3 -0
- package/skills/iranian-payment-gateways/evals/examples/zarinpal-callback.md +3 -0
- package/skills/iranian-payment-gateways/evals/tasks.json +20 -0
- package/skills/iranian-payment-gateways/references/zarinpal-v4.md +44 -0
- package/skills/iranian-payment-gateways/scripts/check-verify.mjs +62 -0
- package/skills/marketplace-search-and-ranking/SKILL.md +93 -0
- package/skills/marketplace-search-and-ranking/evals/examples/index-variant.md +3 -0
- package/skills/marketplace-search-and-ranking/evals/examples/normalize-query.md +7 -0
- package/skills/marketplace-search-and-ranking/evals/tasks.json +29 -0
- package/skills/marketplace-search-and-ranking/references/document-and-ranking.md +56 -0
- package/skills/marketplace-search-and-ranking/scripts/normalize-search-text.mjs +40 -0
- package/skills/mcp-store-tooling/SKILL.md +49 -0
- package/skills/mcp-store-tooling/evals/examples/refund-tool-design.md +3 -0
- package/skills/mcp-store-tooling/evals/examples/remote-server-auth.md +3 -0
- package/skills/mcp-store-tooling/evals/tasks.json +20 -0
- package/skills/mcp-store-tooling/references/mcp-notes.md +67 -0
- package/skills/mcp-store-tooling/scripts/check-tool-definitions.mjs +69 -0
- package/skills/multi-vendor-payouts/SKILL.md +71 -0
- package/skills/multi-vendor-payouts/evals/examples/retry-payout.md +3 -0
- package/skills/multi-vendor-payouts/evals/examples/split-paid-order.md +3 -0
- package/skills/multi-vendor-payouts/evals/tasks.json +30 -0
- package/skills/multi-vendor-payouts/references/ledger.md +35 -0
- package/skills/order-and-webhook-reliability/SKILL.md +99 -0
- package/skills/order-and-webhook-reliability/evals/examples/dedupe-resource-version.md +3 -0
- package/skills/order-and-webhook-reliability/evals/examples/verify-raw-body.md +3 -0
- package/skills/order-and-webhook-reliability/evals/tasks.json +29 -0
- package/skills/order-and-webhook-reliability/references/woocommerce-webhooks.md +58 -0
- package/skills/order-and-webhook-reliability/scripts/verify-hmac-signature.mjs +78 -0
- package/skills/payment-gateway-integration/SKILL.md +90 -0
- package/skills/payment-gateway-integration/evals/examples/confirmed-capture.md +9 -0
- package/skills/payment-gateway-integration/evals/examples/replayed-webhook.md +3 -0
- package/skills/payment-gateway-integration/evals/tasks.json +30 -0
- package/skills/payment-gateway-integration/references/woocommerce-gateway.md +67 -0
- package/skills/product-catalog-modeling/SKILL.md +91 -0
- package/skills/product-catalog-modeling/assets/example-catalog.json +45 -0
- package/skills/product-catalog-modeling/evals/examples/create-variation.md +10 -0
- package/skills/product-catalog-modeling/evals/examples/sync-parent.md +7 -0
- package/skills/product-catalog-modeling/evals/tasks.json +29 -0
- package/skills/product-catalog-modeling/references/variation-model.md +71 -0
- package/skills/product-catalog-modeling/scripts/validate-catalog.mjs +234 -0
- package/skills/product-description-guardrails/SKILL.md +84 -0
- package/skills/product-description-guardrails/evals/examples/facts-only.md +3 -0
- package/skills/product-description-guardrails/evals/examples/label-generated.md +3 -0
- package/skills/product-description-guardrails/evals/tasks.json +30 -0
- package/skills/product-description-guardrails/references/claims.md +24 -0
- package/skills/product-description-guardrails/scripts/check-description.mjs +61 -0
- package/skills/returns-and-refunds/SKILL.md +55 -0
- package/skills/returns-and-refunds/evals/examples/refund-after-inspection.md +3 -0
- package/skills/returns-and-refunds/evals/examples/woocommerce-partial-refund.md +3 -0
- package/skills/returns-and-refunds/evals/tasks.json +20 -0
- package/skills/returns-and-refunds/references/rma-states.md +37 -0
- package/skills/rtl-and-persian-localization/SKILL.md +81 -0
- package/skills/rtl-and-persian-localization/evals/examples/document-direction.md +7 -0
- package/skills/rtl-and-persian-localization/evals/examples/rial-display.md +7 -0
- package/skills/rtl-and-persian-localization/evals/tasks.json +30 -0
- package/skills/rtl-and-persian-localization/references/persian-text.md +51 -0
- package/skills/rtl-and-persian-localization/scripts/normalize-persian.mjs +62 -0
- package/skills/shopify-app-development/SKILL.md +73 -0
- package/skills/shopify-app-development/evals/examples/dedupe-delivery.md +3 -0
- package/skills/shopify-app-development/evals/examples/verify-webhook.md +3 -0
- package/skills/shopify-app-development/evals/tasks.json +29 -0
- package/skills/shopify-app-development/references/auth-and-webhooks.md +44 -0
- package/skills/storefront-accessibility/SKILL.md +59 -0
- package/skills/storefront-accessibility/evals/examples/add-to-cart-announcement.md +3 -0
- package/skills/storefront-accessibility/evals/examples/checkout-errors.md +3 -0
- package/skills/storefront-accessibility/evals/tasks.json +20 -0
- package/skills/storefront-accessibility/references/wcag-checklist.md +41 -0
- package/skills/storefront-performance/SKILL.md +59 -0
- package/skills/storefront-performance/evals/examples/cache-without-leaking-carts.md +3 -0
- package/skills/storefront-performance/evals/examples/slow-product-lcp.md +3 -0
- package/skills/storefront-performance/evals/tasks.json +20 -0
- package/skills/storefront-performance/references/web-vitals.md +55 -0
- package/skills/storefront-performance/scripts/check-web-vitals.mjs +49 -0
- package/skills/stripe-payments/SKILL.md +72 -0
- package/skills/stripe-payments/evals/examples/checkout-session-delayed.md +3 -0
- package/skills/stripe-payments/evals/examples/mark-paid-from-webhook.md +5 -0
- package/skills/stripe-payments/evals/examples/partial-refund.md +3 -0
- package/skills/stripe-payments/evals/tasks.json +27 -0
- package/skills/stripe-payments/references/stripe-objects.md +54 -0
- package/skills/stripe-payments/scripts/verify-stripe-signature.mjs +62 -0
- package/skills/subscription-billing/SKILL.md +76 -0
- package/skills/subscription-billing/evals/examples/cancel-at-period-end.md +3 -0
- package/skills/subscription-billing/evals/examples/one-renewal.md +3 -0
- package/skills/subscription-billing/evals/tasks.json +30 -0
- package/skills/subscription-billing/references/states.md +27 -0
- package/skills/tax-and-shipping/SKILL.md +61 -0
- package/skills/tax-and-shipping/evals/examples/store-tax-lines.md +3 -0
- package/skills/tax-and-shipping/evals/examples/unknown-zone.md +3 -0
- package/skills/tax-and-shipping/evals/tasks.json +30 -0
- package/skills/tax-and-shipping/references/woocommerce.md +22 -0
- package/skills/vector-product-search/SKILL.md +66 -0
- package/skills/vector-product-search/evals/examples/reembed-on-title.md +3 -0
- package/skills/vector-product-search/evals/examples/sku-before-vector.md +3 -0
- package/skills/vector-product-search/evals/tasks.json +30 -0
- package/skills/vector-product-search/references/index.md +40 -0
- package/skills/woocommerce-plugin-development/SKILL.md +84 -0
- package/skills/woocommerce-plugin-development/assets/main-plugin-file.php +28 -0
- package/skills/woocommerce-plugin-development/evals/examples/declare-hpos.md +9 -0
- package/skills/woocommerce-plugin-development/evals/examples/save-order-meta.md +9 -0
- package/skills/woocommerce-plugin-development/evals/tasks.json +32 -0
- package/skills/woocommerce-plugin-development/references/hooks.md +46 -0
- package/skills/woocommerce-plugin-development/references/hpos.md +84 -0
- package/skills/woocommerce-rest-api/SKILL.md +90 -0
- package/skills/woocommerce-rest-api/evals/examples/https-basic-auth.md +8 -0
- package/skills/woocommerce-rest-api/evals/examples/idempotent-order-create.md +7 -0
- package/skills/woocommerce-rest-api/evals/tasks.json +30 -0
- package/skills/woocommerce-rest-api/references/endpoints.md +66 -0
- package/skills/wordpress-plugin-security/SKILL.md +121 -0
- package/skills/wordpress-plugin-security/evals/examples/admin-form-nonce.md +9 -0
- package/skills/wordpress-plugin-security/evals/examples/private-rest-route.md +9 -0
- package/skills/wordpress-plugin-security/evals/tasks.json +31 -0
- package/skills/wordpress-plugin-security/references/review-checklist.md +31 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.3.1] - 2026-10-30
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- The release workflow publishes `@sadrmanesh/commerce-agent-skills` to GitHub Packages after npm, using the workflow's `GITHUB_TOKEN`. npmjs.com remains the main registry.
|
|
8
|
+
- Install docs for GitHub Packages, with the `.npmrc` scope entry, in the installation guide and the README.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- The package and every skill are now version 0.3.1.
|
|
13
|
+
|
|
14
|
+
## [0.3.0] - 2026-10-30
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- Skills for Stripe payments, Iranian payment gateways (Zarinpal request, callback, and verify, with Rial and Toman amounts), inventory across warehouses, returns and refunds, B2B pricing, catalog import and migration, storefront accessibility (WCAG 2.2 AA), storefront performance (Core Web Vitals), and MCP store tooling. Each has a rule, reference notes, and eval fixtures.
|
|
19
|
+
- Node.js checks for Stripe webhook signatures, gateway verify responses, stock allocation, B2B price resolution, import rows, Web Vitals ratings, and MCP tool definitions.
|
|
20
|
+
- `scripts/run-evals.mjs` and `npm run eval`, which score worked examples or a folder of answers against the fixtures, per task, per skill, and overall, with `--skill`, `--min-score`, and `--json`.
|
|
21
|
+
- A "Store operations" category on the docs site.
|
|
22
|
+
- The library is published on npm as `@sadrmanesh/commerce-agent-skills`. `npx @sadrmanesh/commerce-agent-skills init` copies every skill and rule into a project, `add <skill> [<skill> ...]` copies the named ones, and `list` prints them, with `--json`. Skills go to `.agents/skills/` and rules to `.agents/rules/` by default. `--layout root`, `--skills-dir`, `--rules-dir`, `--target`, `--only`, `--no-rules`, `--force`, `--dry-run`, and `--version` are supported, and no network access is needed.
|
|
23
|
+
- The release workflow runs on `vX.Y.Z` tags, creates the GitHub release with the notes from this file, and publishes the package to npm.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- `add` copies the matching rule by default. `--no-rules` turns that off, and `--with-rule` is still accepted.
|
|
28
|
+
- The command now works when started through a symlink, as `npx` and global installs do.
|
|
29
|
+
- The npm package ships only the command, skills, rules, and changelog.
|
|
30
|
+
- The validator is stricter. `metadata.version` must equal the `package.json` version. Skills need `## Gotchas`, `## Verification`, and `## Evaluation` sections and a 100 to 320 character description. Rule headings must match skill headings. Every `must_include` term must be taught by the skill, its rule, or its references. Example files must match a task. Reference links must resolve. Every skill must be in exactly one docs category. Docs and website pages must not use em dashes or the zero-width non-joiner.
|
|
31
|
+
- Every skill is now version 0.3.0. Ten skills gained an `## Evaluation` section.
|
|
32
|
+
- The docs site is now built with MkDocs Material. Skill, rule, and guide pages come straight from the repository, with a catalog page per category, search, a dark theme, and a Persian overview.
|
|
33
|
+
|
|
34
|
+
## 0.2.0 - 2026-10-30
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- Skills for multi-vendor payouts, Shopify apps, a Next.js storefront, Google Merchant product feeds, tax and shipping, subscription billing, fraud and risk review, vector product search, product-description guardrails, and conversion events.
|
|
39
|
+
- Evaluation tasks and a worked example for every skill.
|
|
40
|
+
- A zero-dependency `commerce-agent-skills` command with `list` and `add`. The package is not published to the npm registry.
|
|
41
|
+
- A static docs build, a GitHub Pages workflow, and a manual release workflow that tags a version.
|
|
42
|
+
|
|
43
|
+
## 0.1.0 - 2026-10-30
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- Skills for WooCommerce plugin development, the WooCommerce REST API, WordPress plugin security, payment gateway integration, product catalog modeling, marketplace search and ranking, checkout, Persian and RTL localization, order and webhook reliability, and product structured data.
|
|
48
|
+
- A plain-Markdown rule for each skill.
|
|
49
|
+
- Node.js checks for catalog documents, WooCommerce webhook signatures, Persian and search text, and product JSON-LD.
|
|
50
|
+
- A skill validator, a README catalog generator, tests, and a GitHub Actions workflow.
|
|
51
|
+
- Installation and format notes under `docs/`.
|
|
52
|
+
|
|
53
|
+
[0.3.0]: https://github.com/sadrmanesh/commerce-agent-skills/compare/v0.2.0...v0.3.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Naser Sadrmanesh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,144 @@
|
|
|
1
|
-
#
|
|
1
|
+
# commerce-agent-skills
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Skills and rules for AI coding agents that build e-commerce and marketplace products.
|
|
4
|
+
|
|
5
|
+
**Documentation:** <https://sadrmanesh.github.io/commerce-agent-skills/>
|
|
6
|
+
|
|
7
|
+
The skills follow the [Agent Skills](https://agentskills.io/specification) format: a folder, a `SKILL.md` file with `name` and `description`, and optional reference files and scripts. An agent that supports that format can load them. The format does not name an install path. [Installation](docs/installation.md) explains how to point your agent at these folders.
|
|
8
|
+
|
|
9
|
+
Version 0.3.0 adds store operations to the library. It keeps the twenty skills from 0.1.0 and 0.2.0 and adds Stripe payments, Iranian payment gateways such as Zarinpal, inventory across warehouses, returns and refunds, B2B pricing, catalog import and migration, storefront accessibility, storefront performance, and MCP store tooling. It also adds a stricter validator and an eval runner that scores answers against the fixtures.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- Twenty-nine skills an agent can load when a task matches the skill description.
|
|
14
|
+
- A matching plain-Markdown rule for each skill, for agents that keep short rules in context.
|
|
15
|
+
- Evaluation tasks and a worked example for every skill, and `scripts/run-evals.mjs` to score answers against them.
|
|
16
|
+
- Reference notes and small Node.js tools where a check is better than another paragraph.
|
|
17
|
+
- A strict validator, a catalog built from the skill files, and a docs build, all run in CI. The validator checks versions, required sections, rule headings, that every eval term is taught by the skill, category coverage, and prose style.
|
|
18
|
+
- An `npx @sadrmanesh/commerce-agent-skills` installer that copies every skill and rule, or the ones you name, into your project.
|
|
19
|
+
|
|
20
|
+
## Skill catalog
|
|
21
|
+
|
|
22
|
+
<!-- catalog:start -->
|
|
23
|
+
| Skill | Description |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| [`woocommerce-plugin-development`](skills/woocommerce-plugin-development/SKILL.md) | Build and change WooCommerce plugins with hooks, CRUD data stores, HPOS-safe order access, nonces, capabilities, and gettext. Use when writing or reviewing a plugin that reads or writes WooCommerce products, orders, customers, or checkout. |
|
|
26
|
+
| [`woocommerce-rest-api`](skills/woocommerce-rest-api/SKILL.md) | Call the WooCommerce REST API at wc/v3, including authentication, pagination, batch writes, and webhook registration, and keep it separate from the Store API. Use when an external system integrates with a WooCommerce store over HTTP. |
|
|
27
|
+
| [`wordpress-plugin-security`](skills/wordpress-plugin-security/SKILL.md) | Review and implement WordPress plugin security: capabilities, nonces, sanitization, escaping, prepared SQL, and REST permission callbacks. Use when adding admin screens, AJAX, uploads, hooks, or REST routes in a WordPress or WooCommerce plugin. |
|
|
28
|
+
| [`payment-gateway-integration`](skills/payment-gateway-integration/SKILL.md) | Integrate a payment provider with idempotent charges, signature-checked webhooks, and an explicit map from provider states to order states. Use when adding or changing checkout payment, capture, refund, or payment notification handling. |
|
|
29
|
+
| [`product-catalog-modeling`](skills/product-catalog-modeling/SKILL.md) | Model a sellable catalog of simple products, variants, attributes, SKUs, and stock, and check the model before importing it. Use when designing product data, variation matrices, inventory rules, or catalog imports. |
|
|
30
|
+
| [`marketplace-search-and-ranking`](skills/marketplace-search-and-ranking/SKILL.md) | Index purchasable catalog units and rank them with text relevance, facets, stock, and language-aware matching for Persian and other languages. Use when building marketplace search, filters, relevance, or multilingual product discovery. |
|
|
31
|
+
| [`checkout-ux-and-conversion`](skills/checkout-ux-and-conversion/SKILL.md) | Design checkout so the full cost is visible before payment, guest purchase works, and field or payment errors can be corrected without losing the cart. Use when changing the checkout flow, address form, payment choice, or order confirmation page. |
|
|
32
|
+
| [`rtl-and-persian-localization`](skills/rtl-and-persian-localization/SKILL.md) | Localize a storefront for Persian (fa_IR) and right-to-left layout: logical CSS, digits, Yeh and Kaf, ZWNJ, currency display, and Gregorian storage. Use when building or reviewing Persian, Farsi, or RTL commerce UI. |
|
|
33
|
+
| [`order-and-webhook-reliability`](skills/order-and-webhook-reliability/SKILL.md) | Accept order and payment webhooks with a raw-body signature check, durable deduplication, and reconciliation against the source of truth. Use when handling order events, payment notifications, or outbound webhook delivery. |
|
|
34
|
+
| [`ecommerce-seo-structured-data`](skills/ecommerce-seo-structured-data/SKILL.md) | Add product JSON-LD that matches the visible offer, including price, currency, availability, and images, without a second conflicting Product node. Use when editing product-page SEO, schema.org markup, or merchant listing data. |
|
|
35
|
+
| [`multi-vendor-payouts`](skills/multi-vendor-payouts/SKILL.md) | Split a marketplace order by vendor, record commission as ledger entries, and pay vendors only settled amounts. Use when adding vendor catalogs, commissions, refunds that cross vendors, or payout batches. |
|
|
36
|
+
| [`shopify-app-development`](skills/shopify-app-development/SKILL.md) | Build a Shopify app with the configured Admin API version, session-token auth for embedded admin requests, and HMAC-verified webhooks. Use when creating or changing a Shopify app, Admin GraphQL call, app proxy, or Shopify webhook handler. |
|
|
37
|
+
| [`headless-nextjs-storefront`](skills/headless-nextjs-storefront/SKILL.md) | Build a Next.js storefront that loads catalog data on the server, keeps admin secrets off the client, and revalidates price and stock. Use when adding product, cart, or checkout UI in a Next.js App Router storefront for WooCommerce or another headless commerce API. |
|
|
38
|
+
| [`google-merchant-product-feeds`](skills/google-merchant-product-feeds/SKILL.md) | Build a Google Merchant Center product feed item with the required id, title, description, link, image, availability, and price fields. Use when exporting products to Merchant Center, Content API items, or a product feed file. |
|
|
39
|
+
| [`tax-and-shipping`](skills/tax-and-shipping/SKILL.md) | Calculate tax and shipping from the destination and the store's configured rules, and store the breakdown on the order. Use when changing tax classes, shipping zones, rates, or the amount shown before payment. |
|
|
40
|
+
| [`subscription-billing`](skills/subscription-billing/SKILL.md) | Model subscription state, renewal charges, proration, and dunning without treating a renewal as a new one-time checkout. Use when adding or changing recurring billing, plan changes, cancellation, or failed renewal recovery. |
|
|
41
|
+
| [`fraud-and-risk-basics`](skills/fraud-and-risk-basics/SKILL.md) | Hold or review risky payments using provider signals, velocity, and 3-D Secure without storing card numbers. Use when adding payment risk checks, a manual review queue, or decline handling for card abuse. |
|
|
42
|
+
| [`vector-product-search`](skills/vector-product-search/SKILL.md) | Add vector retrieval beside lexical product search, with one embedding per purchasable unit and exact SKU lookup kept first. Use when adding embedding search, hybrid ranking, or re-embedding after catalog edits. |
|
|
43
|
+
| [`product-description-guardrails`](skills/product-description-guardrails/SKILL.md) | Generate product titles and descriptions only from catalog facts, and block prices, certifications, and medical claims that are not in the record. Use when writing or reviewing generated product copy, Merchant Center text, or locale-specific descriptions. |
|
|
44
|
+
| [`conversion-event-tracking`](skills/conversion-event-tracking/SKILL.md) | Send commerce analytics events with stable names, item ids, and a purchase event that fires once from a confirmed order. Use when adding or changing view_item, add_to_cart, begin_checkout, purchase, or refund tracking. |
|
|
45
|
+
| [`stripe-payments`](skills/stripe-payments/SKILL.md) | Take card and wallet payments with Stripe PaymentIntents or Checkout Sessions, idempotency keys, and signed webhooks that move the order to paid. Use when adding Stripe to a store, handling Stripe webhooks, or refunding through the Stripe API. |
|
|
46
|
+
| [`iranian-payment-gateways`](skills/iranian-payment-gateways/SKILL.md) | Integrate Zarinpal and other Shaparak redirect gateways with a server-side verify call, Rial and Toman amounts, and one paid transition per authority. Use when adding an Iranian payment gateway or fixing callback, verify, or amount handling for IRR or IRT stores. |
|
|
47
|
+
| [`inventory-and-multi-warehouse`](skills/inventory-and-multi-warehouse/SKILL.md) | Track stock per location with on-hand, reserved, and available quantities, reserve at checkout, and allocate orders across warehouses without overselling. Use when adding warehouses or stores as stock locations, reservations, transfers, or order routing. |
|
|
48
|
+
| [`returns-and-refunds`](skills/returns-and-refunds/SKILL.md) | Run returns as a tracked RMA from request to inspection, refund only what the policy and payment allow, and restock only inspected items. Use when building a returns portal, refund rules, exchanges, store credit, or restocking after a return. |
|
|
49
|
+
| [`b2b-pricing`](skills/b2b-pricing/SKILL.md) | Price for business buyers with customer-group price lists, quantity tiers, contract prices, minimum quantities, net terms, and tax exemption, resolved on the server. Use when adding wholesale or B2B prices, tiered pricing, quotes, or company accounts to a store. |
|
|
50
|
+
| [`catalog-import-and-migration`](skills/catalog-import-and-migration/SKILL.md) | Import, export, and migrate product catalogs with stable SKU keys, a dry run, parent-before-variation order, batched writes, and URL redirects. Use when moving a store between platforms, bulk importing CSV or JSON products, or exporting a catalog for another system. |
|
|
51
|
+
| [`storefront-accessibility`](skills/storefront-accessibility/SKILL.md) | Build product, cart, and checkout pages that meet WCAG 2.2 AA: keyboard use, visible focus, labels and autocomplete, announced errors and cart updates, contrast, and target size. Use when building or reviewing storefront UI, forms, filters, carousels, or checkout for accessibility. |
|
|
52
|
+
| [`storefront-performance`](skills/storefront-performance/SKILL.md) | Improve storefront Core Web Vitals (LCP, INP, CLS) using field data at the 75th percentile, image and font loading, caching of catalog pages, and lighter third-party scripts. Use when product or category pages feel slow, Web Vitals fail, or a theme, app, or script change needs a performance check. |
|
|
53
|
+
| [`mcp-store-tooling`](skills/mcp-store-tooling/SKILL.md) | Design Model Context Protocol servers for stores: read and write tools with annotations, input and output schemas, scopes, dry runs and confirmation for risky writes, resources, and remote auth. Use when exposing a store's catalog, orders, or customers to an agent through MCP, or reviewing such a server. |
|
|
54
|
+
<!-- catalog:end -->
|
|
55
|
+
|
|
56
|
+
## Install
|
|
57
|
+
|
|
58
|
+
Install the skills into your project with npx. Node.js 20 or newer is required, and nothing is downloaded after the package itself:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npx @sadrmanesh/commerce-agent-skills init
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
That copies every skill to `.agents/skills/` and every rule to `.agents/rules/`. To pick skills, or to write them where your agent looks:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npx @sadrmanesh/commerce-agent-skills list
|
|
68
|
+
npx @sadrmanesh/commerce-agent-skills add woocommerce-plugin-development stripe-payments
|
|
69
|
+
npx @sadrmanesh/commerce-agent-skills init --layout root
|
|
70
|
+
npx @sadrmanesh/commerce-agent-skills init --skills-dir path/to/skills --rules-dir path/to/rules
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`init` skips skills that are already installed, `--force` replaces them, and `--dry-run` shows what would be written. From a checkout, `node bin/commerce-agent-skills.mjs` takes the same arguments. Details are in [docs/installation.md](docs/installation.md) and [docs/cli.md](docs/cli.md).
|
|
74
|
+
|
|
75
|
+
The package is on npmjs.com and, with the same name, on GitHub Packages. npmjs.com is the default; [docs/installation.md](docs/installation.md#install-from-github-packages) has the `.npmrc` lines for GitHub Packages.
|
|
76
|
+
|
|
77
|
+
## Work on the library
|
|
78
|
+
|
|
79
|
+
Clone the repository and check the skills:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
git clone https://github.com/sadrmanesh/commerce-agent-skills.git
|
|
83
|
+
cd commerce-agent-skills
|
|
84
|
+
node scripts/validate-skills.mjs
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Node.js 20 or newer is required for the validator, the docs generator, and the command. The docs site also needs Python and MkDocs. This repository is a skill library, not a dependency of the storefront.
|
|
88
|
+
|
|
89
|
+
## Usage
|
|
90
|
+
|
|
91
|
+
Agents read `name` and `description` to decide whether a skill applies, then read the `SKILL.md` body. Reference files and scripts are loaded only when the skill points to them. Keep instructions in `SKILL.md` and longer notes under `references/`.
|
|
92
|
+
|
|
93
|
+
Rules in [`rules/`](rules/) are not skills. They are short constraints you can install as always-on guidance. A skill is for a task. A rule is for every task in that area. See [docs/rules.md](docs/rules.md).
|
|
94
|
+
|
|
95
|
+
Regenerate the catalog table after a description change:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
node scripts/generate-catalog.mjs
|
|
99
|
+
node scripts/generate-catalog.mjs --check
|
|
100
|
+
node --test
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Score answers against the eval fixtures:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
node scripts/run-evals.mjs
|
|
107
|
+
node scripts/run-evals.mjs --answers ./answers --min-score 0.8
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The first command checks the worked examples. The second reads `answers/<skill>/<task-id>.md`, prints a score per skill, and exits with status 1 below the threshold.
|
|
111
|
+
|
|
112
|
+
The skill format is documented in [docs/skill-format.md](docs/skill-format.md). Evaluation fixtures and the runner are documented in [docs/evaluations.md](docs/evaluations.md).
|
|
113
|
+
|
|
114
|
+
## Docs site
|
|
115
|
+
|
|
116
|
+
The documentation lives at [sadrmanesh.github.io/commerce-agent-skills](https://sadrmanesh.github.io/commerce-agent-skills/). It is built with MkDocs Material, and the skill, rule, and guide pages are generated from this repository by `scripts/build-docs.mjs`, so they always match the files here. `.github/workflows/pages.yml` deploys it on pushes to `main`. See [docs/github-pages.md](docs/github-pages.md).
|
|
117
|
+
|
|
118
|
+
`.github/workflows/release.yml` runs when a `vX.Y.Z` tag is pushed. It checks that the tag matches `package.json`, runs the validator, evals, and tests, creates the GitHub release if it does not exist, and publishes `@sadrmanesh/commerce-agent-skills` to npm and to GitHub Packages, which uses the workflow's `GITHUB_TOKEN`. Running it by hand with a version tags that version first.
|
|
119
|
+
|
|
120
|
+
## Roadmap
|
|
121
|
+
|
|
122
|
+
0.3.0 adds nine store operations skills, the eval runner, stricter validation, and the `npx @sadrmanesh/commerce-agent-skills` installer. The runner does not send tasks to a live agent: it scores answer files you collect.
|
|
123
|
+
|
|
124
|
+
Later releases can add:
|
|
125
|
+
|
|
126
|
+
- Runnable reference services for the payout ledger and a feed upload, with the same checks the local scripts already apply.
|
|
127
|
+
- More store platforms, written to the same level of API detail as the WooCommerce and Shopify skills.
|
|
128
|
+
- More payment providers, written like the Stripe and Zarinpal skills.
|
|
129
|
+
- Graded eval rubrics beyond substring checks.
|
|
130
|
+
|
|
131
|
+
## Contributing
|
|
132
|
+
|
|
133
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). Run the validator before opening a pull request. New skills need a matching rule, a row in `skills/catalog-order.txt`, and a place in `website/categories.json`.
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
[MIT](LICENSE). Copyright (c) 2026 Naser Sadrmanesh.
|
|
138
|
+
|
|
139
|
+
## Author
|
|
140
|
+
|
|
141
|
+
Naser Sadrmanesh
|
|
142
|
+
|
|
143
|
+
- GitHub: [https://github.com/sadrmanesh](https://github.com/sadrmanesh)
|
|
144
|
+
- Website: [https://sadrmanesh.github.io](https://sadrmanesh.github.io)
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import { cp, mkdir, readdir, readFile, rm, stat } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { parseFrontmatter, splitFrontmatter } from "../scripts/lib/frontmatter.mjs";
|
|
7
|
+
|
|
8
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Where skills and rules land inside a project.
|
|
12
|
+
* `agents` keeps both under a hidden .agents directory, which many agents scan.
|
|
13
|
+
* `root` writes skills/ and rules/ at the top of the project.
|
|
14
|
+
*/
|
|
15
|
+
export const LAYOUTS = Object.freeze({
|
|
16
|
+
agents: Object.freeze({ skills: ".agents/skills", rules: ".agents/rules" }),
|
|
17
|
+
root: Object.freeze({ skills: "skills", rules: "rules" }),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const DEFAULT_LAYOUT = "agents";
|
|
21
|
+
|
|
22
|
+
export function packageSkillsDir(root = packageRoot) {
|
|
23
|
+
return path.join(root, "skills");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function packageRulesDir(root = packageRoot) {
|
|
27
|
+
return path.join(root, "rules");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function packageVersion(root = packageRoot) {
|
|
31
|
+
const pkg = JSON.parse(await readFile(path.join(root, "package.json"), "utf8"));
|
|
32
|
+
return pkg.version;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function isDirectory(target) {
|
|
36
|
+
return stat(target).then(
|
|
37
|
+
(info) => info.isDirectory(),
|
|
38
|
+
() => false,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function isFile(target) {
|
|
43
|
+
return stat(target).then(
|
|
44
|
+
(info) => info.isFile(),
|
|
45
|
+
() => false,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function listSkillRecords(root = packageRoot) {
|
|
50
|
+
const skillsDir = packageSkillsDir(root);
|
|
51
|
+
const entries = await readdir(skillsDir, { withFileTypes: true });
|
|
52
|
+
const records = [];
|
|
53
|
+
for (const entry of entries) {
|
|
54
|
+
if (!entry.isDirectory()) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const skillPath = path.join(skillsDir, entry.name, "SKILL.md");
|
|
58
|
+
if (!(await isFile(skillPath))) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const text = await readFile(skillPath, "utf8");
|
|
62
|
+
const { yaml } = splitFrontmatter(text);
|
|
63
|
+
const data = parseFrontmatter(yaml);
|
|
64
|
+
records.push({
|
|
65
|
+
name: entry.name,
|
|
66
|
+
description: typeof data.description === "string" ? data.description : "",
|
|
67
|
+
hasRule: await isFile(path.join(packageRulesDir(root), `${entry.name}.md`)),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
records.sort((a, b) => a.name.localeCompare(b.name));
|
|
71
|
+
return records;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Resolve the skills and rules directories for an install.
|
|
76
|
+
* `dir` is the older single-directory form: skills go to `dir`, rules to a
|
|
77
|
+
* `rules` directory next to it.
|
|
78
|
+
*/
|
|
79
|
+
export function resolveTargets({ target = ".", layout, skillsDir, rulesDir, dir } = {}) {
|
|
80
|
+
const base = path.resolve(target);
|
|
81
|
+
if (dir !== undefined) {
|
|
82
|
+
if (typeof dir !== "string" || dir.trim() === "") {
|
|
83
|
+
throw new Error("--dir needs a path.");
|
|
84
|
+
}
|
|
85
|
+
const skills = path.resolve(base, dir);
|
|
86
|
+
return {
|
|
87
|
+
skills,
|
|
88
|
+
rules: rulesDir ? path.resolve(base, rulesDir) : path.join(path.dirname(skills), "rules"),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const layoutName = layout ?? DEFAULT_LAYOUT;
|
|
92
|
+
const preset = LAYOUTS[layoutName];
|
|
93
|
+
if (!preset) {
|
|
94
|
+
throw new Error(`Unknown layout: ${layoutName}. Use one of: ${Object.keys(LAYOUTS).join(", ")}.`);
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
skills: path.resolve(base, skillsDir ?? preset.skills),
|
|
98
|
+
rules: path.resolve(base, rulesDir ?? preset.rules),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function checkSkillName(name, known) {
|
|
103
|
+
if (typeof name !== "string" || name === "" || !/^[a-z0-9][a-z0-9-]*$/.test(name)) {
|
|
104
|
+
throw new Error(`Invalid skill name: ${name || "(empty)"}`);
|
|
105
|
+
}
|
|
106
|
+
if (!known.has(name)) {
|
|
107
|
+
throw new Error(`Unknown skill: ${name}. Run "commerce-agent-skills list" to see the names.`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Copy skills (and their rules) into a project.
|
|
113
|
+
* Returns one entry per skill: { name, status, destination, rulePath }.
|
|
114
|
+
* status is "added", "replaced", "skipped" (exists, onExisting = "skip"),
|
|
115
|
+
* or "planned" when dryRun is set.
|
|
116
|
+
*/
|
|
117
|
+
export async function installSkills({
|
|
118
|
+
names,
|
|
119
|
+
target = ".",
|
|
120
|
+
layout,
|
|
121
|
+
skillsDir,
|
|
122
|
+
rulesDir,
|
|
123
|
+
dir,
|
|
124
|
+
rules = true,
|
|
125
|
+
force = false,
|
|
126
|
+
onExisting = "error",
|
|
127
|
+
dryRun = false,
|
|
128
|
+
root = packageRoot,
|
|
129
|
+
}) {
|
|
130
|
+
const records = await listSkillRecords(root);
|
|
131
|
+
const known = new Map(records.map((record) => [record.name, record]));
|
|
132
|
+
const wanted = names === undefined ? records.map((record) => record.name) : [...new Set(names)];
|
|
133
|
+
if (wanted.length === 0) {
|
|
134
|
+
throw new Error("No skills selected.");
|
|
135
|
+
}
|
|
136
|
+
for (const name of wanted) {
|
|
137
|
+
checkSkillName(name, known);
|
|
138
|
+
}
|
|
139
|
+
const targets = resolveTargets({ target, layout, skillsDir, rulesDir, dir });
|
|
140
|
+
|
|
141
|
+
const plan = [];
|
|
142
|
+
for (const name of wanted) {
|
|
143
|
+
const destination = path.join(targets.skills, name);
|
|
144
|
+
const exists = await isDirectory(destination);
|
|
145
|
+
if (exists && !force && onExisting === "error") {
|
|
146
|
+
throw new Error(`${destination} already exists. Pass --force to replace it.`);
|
|
147
|
+
}
|
|
148
|
+
const rulePath = rules && known.get(name).hasRule ? path.join(targets.rules, `${name}.md`) : undefined;
|
|
149
|
+
plan.push({ name, exists, destination, rulePath });
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const results = [];
|
|
153
|
+
for (const item of plan) {
|
|
154
|
+
if (item.exists && !force) {
|
|
155
|
+
results.push({ name: item.name, status: "skipped", destination: item.destination });
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (dryRun) {
|
|
159
|
+
results.push({ name: item.name, status: "planned", destination: item.destination, rulePath: item.rulePath });
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
await mkdir(path.dirname(item.destination), { recursive: true });
|
|
163
|
+
if (item.exists) {
|
|
164
|
+
await rm(item.destination, { recursive: true, force: true });
|
|
165
|
+
}
|
|
166
|
+
await cp(path.join(packageSkillsDir(root), item.name), item.destination, { recursive: true });
|
|
167
|
+
if (item.rulePath) {
|
|
168
|
+
await mkdir(path.dirname(item.rulePath), { recursive: true });
|
|
169
|
+
await cp(path.join(packageRulesDir(root), `${item.name}.md`), item.rulePath, { force: true });
|
|
170
|
+
}
|
|
171
|
+
results.push({
|
|
172
|
+
name: item.name,
|
|
173
|
+
status: item.exists ? "replaced" : "added",
|
|
174
|
+
destination: item.destination,
|
|
175
|
+
rulePath: item.rulePath,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return { targets, results };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Copy one skill. Kept for scripts written against 0.2.0. */
|
|
182
|
+
export async function addSkill({ name, dir, force = false, withRule = false, root = packageRoot }) {
|
|
183
|
+
if (typeof dir !== "string" || dir.trim() === "") {
|
|
184
|
+
throw new Error("--dir is required.");
|
|
185
|
+
}
|
|
186
|
+
const { results } = await installSkills({ names: [name], dir, force, rules: withRule, root });
|
|
187
|
+
return { destination: results[0].destination, rulePath: results[0].rulePath };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const USAGE = `Usage:
|
|
191
|
+
commerce-agent-skills list [--json]
|
|
192
|
+
commerce-agent-skills init [options]
|
|
193
|
+
commerce-agent-skills add <skill> [<skill> ...] [options]
|
|
194
|
+
|
|
195
|
+
Commands:
|
|
196
|
+
list Print every skill with its description.
|
|
197
|
+
init Copy the whole library, or the skills named with --only.
|
|
198
|
+
add Copy the named skills.
|
|
199
|
+
|
|
200
|
+
Options:
|
|
201
|
+
--target <dir> Project directory to install into. Default: current directory.
|
|
202
|
+
--layout <name> agents (.agents/skills and .agents/rules, default)
|
|
203
|
+
or root (skills/ and rules/).
|
|
204
|
+
--skills-dir <path> Skills directory, relative to --target. Overrides the layout.
|
|
205
|
+
--rules-dir <path> Rules directory, relative to --target. Overrides the layout.
|
|
206
|
+
--dir <path> Skills directory for add, with rules in a sibling rules/ directory.
|
|
207
|
+
--only <a,b> init: install only these skills.
|
|
208
|
+
--no-rules Do not copy the matching rules.
|
|
209
|
+
--force Replace skills that are already installed.
|
|
210
|
+
--dry-run Print what would be copied and write nothing.
|
|
211
|
+
-h, --help Show this help.
|
|
212
|
+
-v, --version Print the version.`;
|
|
213
|
+
|
|
214
|
+
const VALUE_FLAGS = new Set(["--target", "--layout", "--skills-dir", "--rules-dir", "--dir", "--only"]);
|
|
215
|
+
const BOOLEAN_FLAGS = new Set(["--no-rules", "--force", "--dry-run", "--with-rule", "--json", "--help", "-h"]);
|
|
216
|
+
|
|
217
|
+
export function parseArgs(args) {
|
|
218
|
+
const options = {};
|
|
219
|
+
const positionals = [];
|
|
220
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
221
|
+
const arg = args[index];
|
|
222
|
+
if (arg.startsWith("-")) {
|
|
223
|
+
const [flag, inline] = arg.includes("=") ? [arg.slice(0, arg.indexOf("=")), arg.slice(arg.indexOf("=") + 1)] : [arg, undefined];
|
|
224
|
+
if (VALUE_FLAGS.has(flag)) {
|
|
225
|
+
const value = inline ?? args[index + 1];
|
|
226
|
+
if (inline === undefined) {
|
|
227
|
+
index += 1;
|
|
228
|
+
}
|
|
229
|
+
if (value === undefined || (inline === undefined && value.startsWith("--"))) {
|
|
230
|
+
throw new Error(`${flag} needs a value.`);
|
|
231
|
+
}
|
|
232
|
+
options[flag.slice(2)] = value;
|
|
233
|
+
} else if (BOOLEAN_FLAGS.has(flag) && inline === undefined) {
|
|
234
|
+
options[flag === "-h" ? "help" : flag.replace(/^--/, "")] = true;
|
|
235
|
+
} else {
|
|
236
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
positionals.push(arg);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return { options, positionals };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function display(target) {
|
|
246
|
+
const relative = path.relative(process.cwd(), target);
|
|
247
|
+
return relative === "" ? "." : relative.startsWith("..") ? target : relative;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function report({ targets, results }, dryRun) {
|
|
251
|
+
const verb = dryRun ? "Would add" : "Added";
|
|
252
|
+
for (const result of results) {
|
|
253
|
+
if (result.status === "skipped") {
|
|
254
|
+
console.log(`Skipped ${result.name}: ${display(result.destination)} exists (use --force to replace)`);
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
const label = result.status === "replaced" ? "Replaced" : verb;
|
|
258
|
+
const rule = result.rulePath ? ` and ${display(result.rulePath)}` : "";
|
|
259
|
+
console.log(`${label} ${result.name} at ${display(result.destination)}${rule}`);
|
|
260
|
+
}
|
|
261
|
+
const copied = results.filter((result) => result.status !== "skipped").length;
|
|
262
|
+
console.log(
|
|
263
|
+
`${dryRun ? "Planned" : "Done"}: ${copied} of ${results.length} skills. Skills: ${display(targets.skills)}, rules: ${display(targets.rules)}`,
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export async function main(argv, root = packageRoot) {
|
|
268
|
+
const [command, ...rest] = argv;
|
|
269
|
+
if (command === undefined || command === "help" || command === "--help" || command === "-h") {
|
|
270
|
+
console.log(USAGE);
|
|
271
|
+
return command === undefined ? 2 : 0;
|
|
272
|
+
}
|
|
273
|
+
if (command === "--version" || command === "-v") {
|
|
274
|
+
console.log(await packageVersion(root));
|
|
275
|
+
return 0;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
let parsed;
|
|
279
|
+
try {
|
|
280
|
+
parsed = parseArgs(rest);
|
|
281
|
+
} catch (error) {
|
|
282
|
+
console.error(error.message);
|
|
283
|
+
console.error(USAGE);
|
|
284
|
+
return 2;
|
|
285
|
+
}
|
|
286
|
+
const { options, positionals } = parsed;
|
|
287
|
+
if (options.help) {
|
|
288
|
+
console.log(USAGE);
|
|
289
|
+
return 0;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (command === "list") {
|
|
293
|
+
if (positionals.length > 0) {
|
|
294
|
+
console.error(USAGE);
|
|
295
|
+
return 2;
|
|
296
|
+
}
|
|
297
|
+
const records = await listSkillRecords(root);
|
|
298
|
+
if (options.json) {
|
|
299
|
+
console.log(JSON.stringify(records.map(({ name, description }) => ({ name, description })), null, 2));
|
|
300
|
+
} else {
|
|
301
|
+
for (const record of records) {
|
|
302
|
+
console.log(`${record.name}\t${record.description}`);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return 0;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (command === "init" || command === "add") {
|
|
309
|
+
if (command === "init" && positionals.length > 0) {
|
|
310
|
+
console.error(`init takes no skill names. Use --only ${positionals.join(",")} or add.`);
|
|
311
|
+
return 2;
|
|
312
|
+
}
|
|
313
|
+
if (command === "add" && positionals.length === 0) {
|
|
314
|
+
console.error("add needs at least one skill name.");
|
|
315
|
+
console.error(USAGE);
|
|
316
|
+
return 2;
|
|
317
|
+
}
|
|
318
|
+
if (command === "add" && options.only) {
|
|
319
|
+
console.error("--only is for init. Pass skill names to add.");
|
|
320
|
+
return 2;
|
|
321
|
+
}
|
|
322
|
+
const names =
|
|
323
|
+
command === "add"
|
|
324
|
+
? positionals
|
|
325
|
+
: options.only
|
|
326
|
+
? options.only.split(",").map((name) => name.trim()).filter(Boolean)
|
|
327
|
+
: undefined;
|
|
328
|
+
try {
|
|
329
|
+
const outcome = await installSkills({
|
|
330
|
+
names,
|
|
331
|
+
target: options.target ?? ".",
|
|
332
|
+
layout: options.layout,
|
|
333
|
+
skillsDir: options["skills-dir"],
|
|
334
|
+
rulesDir: options["rules-dir"],
|
|
335
|
+
dir: options.dir,
|
|
336
|
+
rules: !options["no-rules"],
|
|
337
|
+
force: Boolean(options.force),
|
|
338
|
+
onExisting: command === "init" ? "skip" : "error",
|
|
339
|
+
dryRun: Boolean(options["dry-run"]),
|
|
340
|
+
root,
|
|
341
|
+
});
|
|
342
|
+
report(outcome, Boolean(options["dry-run"]));
|
|
343
|
+
return 0;
|
|
344
|
+
} catch (error) {
|
|
345
|
+
console.error(error.message);
|
|
346
|
+
return 1;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
console.error(`Unknown command: ${command}`);
|
|
351
|
+
console.error(USAGE);
|
|
352
|
+
return 2;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// npx and global installs start the command through a symlink, so compare real paths.
|
|
356
|
+
function realpathSafe(file) {
|
|
357
|
+
try {
|
|
358
|
+
return realpathSync(path.resolve(file));
|
|
359
|
+
} catch {
|
|
360
|
+
return path.resolve(file);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const isCli = Boolean(process.argv[1]) && realpathSafe(fileURLToPath(import.meta.url)) === realpathSafe(process.argv[1]);
|
|
365
|
+
|
|
366
|
+
if (isCli) {
|
|
367
|
+
process.exitCode = await main(process.argv.slice(2));
|
|
368
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,54 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sadrmanesh/commerce-agent-skills",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Tool-agnostic skills and rules for AI coding agents that build e-commerce and marketplace products.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agent-skills",
|
|
7
|
+
"skills",
|
|
8
|
+
"ecommerce",
|
|
9
|
+
"woocommerce",
|
|
10
|
+
"shopify",
|
|
11
|
+
"stripe",
|
|
12
|
+
"marketplace",
|
|
13
|
+
"coding-agents",
|
|
14
|
+
"rules",
|
|
15
|
+
"cli"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": "Naser Sadrmanesh <info.sadrmanesh@gmail.com>",
|
|
19
|
+
"type": "module",
|
|
20
|
+
"bin": {
|
|
21
|
+
"commerce-agent-skills": "./bin/commerce-agent-skills.mjs"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"bin",
|
|
25
|
+
"skills",
|
|
26
|
+
"rules",
|
|
27
|
+
"scripts/lib/frontmatter.mjs",
|
|
28
|
+
"CHANGELOG.md"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"validate": "node scripts/validate-skills.mjs",
|
|
35
|
+
"catalog": "node scripts/generate-catalog.mjs",
|
|
36
|
+
"catalog:check": "node scripts/generate-catalog.mjs --check",
|
|
37
|
+
"docs": "node scripts/build-docs.mjs && mkdocs build --strict -f build/mkdocs.yml",
|
|
38
|
+
"test": "node --test",
|
|
39
|
+
"eval": "node scripts/run-evals.mjs",
|
|
40
|
+
"prepublishOnly": "node scripts/validate-skills.mjs && node scripts/generate-catalog.mjs --check && node --test",
|
|
41
|
+
"pack:check": "npm pack --dry-run"
|
|
42
|
+
},
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/sadrmanesh/commerce-agent-skills.git"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://sadrmanesh.github.io/commerce-agent-skills/",
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/sadrmanesh/commerce-agent-skills/issues"
|
|
50
|
+
},
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# B2B pricing
|
|
2
|
+
|
|
3
|
+
- Resolve every B2B price on the server with one function shared by catalog, cart, and order.
|
|
4
|
+
- Model prices as price lists with currency, validity, groups or companies, and quantity tiers.
|
|
5
|
+
- Contract prices win when they exist. Otherwise apply one documented rule: lowest price or priority.
|
|
6
|
+
- Use the highest tier whose `minQuantity` the line meets. Show the next tier to the buyer.
|
|
7
|
+
- Enforce minimum quantities and order multiples in the cart.
|
|
8
|
+
- Never cache a group price page for everyone. Vary by group.
|
|
9
|
+
- Net terms need a credit limit check against open invoices.
|
|
10
|
+
- Store tax exemption evidence or the validated VAT id on the order.
|
|
11
|
+
- The price on a placed order line never changes when a list changes.
|