Headless Commerce v1.0.0 MIT
Catalog Data Audit (Files Only)
Use when auditing a storefront catalog for drift. Produces a per-row CSV of defects and a named-rule report, without changing live data.
Features
- Confirms the live host and the data-of-record file before any rule runs.
- Joins the repo catalog to the public feed and asserts that every field both expose agrees.
- Applies named rule codes (R1 to R7 plus SKU, size, category, price, image and data codes) that a script can re-run and count.
- Writes a six-column CSV where every row cites the repo path or live URL that proves it.
- Generates the CSV and the per-code counts from one regenerator script, so no row is typed by hand.
Benefits
- Every finding can be reproduced: a reviewer re-runs the script and gets the same counts.
- Proposals and flags stay separate from changes, so nothing ships by accident.
- Pre-launch states and bot-wall failures are labelled, so they are not counted as defects.
- Stock-sync and sitemap risks are named before anyone renames a SKU or moves a category.
Install
From the tap (or GitHub path)
hermes skills install shagghiesuperstar/hermes-skills/skills/catalog-data-audit --category commerce
Direct URL
hermes skills install https://raw.githubusercontent.com/shagghiesuperstar/hermes-skills/main/skills/catalog-data-audit/SKILL.md --category commerce
Get the skill
Related skills
- Web QualityCRO and UX Baseline Audit (One Storefront, Read-Only)Use when auditing a storefront's conversion and UX. Read-only, ranked backlog with evidence per row.
- Agent OrchestrationData-Artifact Adversarial ReviewUse when reviewing another agent's data deliverable. Covers CSV, JSON and other data outputs, such as a list, extract, or catalog audit, before a merge. Verifies claims by re-execution.
- Headless CommerceRegulated-Catalog Content DraftsUse when drafting copy for a regulated online store. Output is one draft pull request, never merged, with a compliance lint that must report zero hits.
- Security & SecretsGit Remote HygieneUse when pushing from a repo or checking a remote URL. A remote URL may carry a token. Covers redacted remote checks, credential helpers, explicit push refspecs, and token rotation.
Related repos
The skill file
Catalog Data Audit (Files Only)
Overview
A read-only audit of a storefront catalog. It compares the data of record in the repo with the public feed and the shopper-facing pages, then lists every row that breaks a named rule for naming, SKUs, sizes, categories, prices, media or copy. The deliverable is evidence for an owner to decide on. The audit changes no SKU, price, category, setting or order.
When to Use
- Titles, SKUs or categories need a consistency review before a launch, migration or feed change.
- The spreadsheet or source JSON and the live feed disagree, and the drift must be listed row by row.
- A files-only pull request with a CSV of catalog defects is the requested output.
Skip it for UX or conversion reviews, for reviewing a CSV someone else produced (use data-artifact-adversarial-review), and for building a new prospect list.
Features
- Confirms the live host and the data-of-record file before any rule runs.
- Joins the repo catalog to the public feed and asserts that every field both expose agrees.
- Applies named rule codes (R1 to R7 plus SKU, size, category, price, image and data codes) that a script can re-run and count.
- Writes a six-column CSV where every row cites the repo path or live URL that proves it.
- Generates the CSV and the per-code counts from one regenerator script, so no row is typed by hand.
Benefits
- Every finding can be reproduced: a reviewer re-runs the script and gets the same counts.
- Proposals and flags stay separate from changes, so nothing ships by accident.
- Pre-launch states and bot-wall failures are labelled, so they are not counted as defects.
- Stock-sync and sitemap risks are named before anyone renames a SKU or moves a category.
Procedure
Confirm the live host from the repo's published config (site metadata, redirects, proof or launch notes), not from memory. Request the feed and expect 200. State any inference in the report's first paragraph.
curl -sI "https://<storefront-host>/feeds/catalog.json"Identify the data of record. Many repos ship two copies of the catalog JSON: a source copy and a build-time copy. Diff them and record the SHA of the copy you used. The diff is itself a sanity check.
diff -q "<source-dir>/catalog.json" "<storefront-dir>/catalog.json"- For a regulated catalog, find the repo's claim test and any mandated footer. Keep mandated text verbatim. Do not introduce claim terms that the banned-claims list covers into the audit's prose or the proposed values.
Clone the repo as a blobless sparse checkout. A full clone of a large storefront can exceed a 180-second foreground timeout.
git clone --filter=blob:none --no-checkout https://github.com/<owner>/<repo>.git cd <repo> git sparse-checkout init --cone git sparse-checkout set <data-dir> <scripts-dir> <lib-dir> git checkout main- Read every file that establishes catalog identity: both JSON copies, any CSV sheet, the build script, the seed script that assigns categories and images, and any sidecar copy. Reading is the only operation on the repo.
- Keep live access to GET requests at 1.5 per second or fewer. Fetch the feed, product pages and image files only. Never submit a form, log in, pass an age gate, or call an admin API. Record a 403 as "bot wall or rate limit, not a defect", not as a finding.
- Join repo to live before writing any rule. For handle, title, SKU, size and price, assert that repo equals feed. A mismatch becomes its own row, class
DATA_REPO_VS_LIVE_DRIFT. Do not propose SKU, title or category changes for a field where repo and live disagree. Express every finding as a named code, not a free-text reason. The script re-applies each code, and the report counts them. The codes used in this audit:
R1formula, code or sequence string inside a title (a long identifier string belongs in the spec block)R2title longer than the cap (for example 60 characters)R3non-ASCII punctuation such as dashes or smart quotesR4parenthetical that expands an abbreviation, not a code or an alternate nameR5category name or boilerplate phrase inside a titleR6title does not lead with the house code that the handle and sheet useR7title less specific than the item its description namesCATEGORY_PLACEMENT,COA_MISSING,IMAGE_DUPLICATE,IMAGE_ALT,PRICE_PER_UNIT_OUTLIER,PRICE_TIER_SPREAD,SIZE_NOTATION,SKU_PATTERNDATA_CSV_TITLE_DRIFT,DATA_STALE_COPY,DATA_NULL_PLACEHOLDER,DATA_MIXED_TYPE,DATA_FEED_VS_PAGE_CATEGORY
- Write
audit.csvwith six columns, in this order:product,field,issue,current,proposed,source. Truncatecurrentto about 70 characters andproposedto about 60. Every cell in every column must be non-empty.issueis the code followed by one clause of reason.sourceis the repo path or the live URL that proves the row. - Gate every SKU rename. The script checks each proposed SKU against the full existing SKU set and refuses duplicates. A rename that needs an external stock or order map is written as
rename gated on <external SKU map>; no change made. - Write the regenerator script (
build_audit.py). It reads both JSON copies and the CSV, asserts they agree, reads a cached copy of the live feed, applies each rule, writesaudit.csv, and prints per-code counts on one line. A reviewer re-runspython3 build_audit.py --repo .and must see the same counts the report cites. - Write
report.mdin this order: scope and live URL with the feed hash prefix; what was read; result at a glance (fields that agree, fields that disagree, clean checks with zero findings); the named rule definitions; issue counts per code with rows, distinct products and draft-only rows, all taken from the script; products that break the standard, grouped by code; risks and pre-mortem; limits of the audit. - Open one draft pull request from
origin/mainwith one commit. Do not merge it. A second batch of issues is a new branch and a new pull request.
Pitfalls
- Storefront URLs are often missing from the repo. Inferring one is fine when the inference and its derivation are stated, and the owner is asked to confirm it.
- Publishable keys are often absent from the page source. Many storefronts fetch on the server. When no key appears in the HTML or linked scripts, use the public feed as the anonymous read and say so in the first paragraph of the pull request body.
- A key scoped to one project is rejected by another. A
400 not_allowedfrom one project means the key belongs to a different sales channel. Do not retry the key across endpoints; ask the owner for the correct key. - Two catalog copies can drift. The reference copy is the record. A difference between the copies is a finding, not a reason to pick the more convenient one.
- An empty field in the feed is not an empty field in the shop. When the feed has no categories but the product page shows one, file a
DATA_FEED_VS_PAGE_CATEGORYrow. Do not count every product as uncategorised. - A stale sidecar copy is deleted or regenerated, not hand-edited. Propose deletion or regeneration only. Writing replacement values by hand turns the audit into an editor.
- A brand field that is empty on every row needs a recovery rule. Name the rule in the report's method section (for example, matching the first variant SKU against a public brand listing) and label unmatched rows
(no brand listed). - Repeated images across products usually come from a hash or a fixed pool. Name the mechanism in the report. The proposed fix is one product-specific image per product with real alt text.
- Duplicate titles across variants are often intentional. Option or size variants published as separate products with the same title are the usual cause. Say so, and leave the proposed value as
<owner decision; no rename proposed>. - A price outlier is a flag, not a fix. The proposed value is
no price change proposed; confirm against supplier data. A number in that cell is a defect. - A SKU rename without the external stock map orphans stock and open orders. Gate the rename and name the map the rename depends on.
- A pre-launch "every item is N of N" finding needs its caveat. "No certificates published" carries no impact before launch. State the caveat next to the count.
- A finding concentrated in one regulated class is a policy question. Split the count by class and ask the owner which document applies before calling the rest defects.
- Carried-forward URLs go stale. Re-probe every URL cited as found in an earlier run, and record the probe time next to it.
- A setting that is off on purpose is not drift. A stock-tracking flag disabled by decision is the default state. Say so in the report instead of dropping the check.
- Every self-described number is derived. Row counts, byte totals, request counts and hash prefixes come from the files and the script output, not from memory.
Verification
- Every row of
audit.csvhas non-emptyproduct,field,issue,current,proposedandsource. - Re-running the regenerator prints the same per-code counts that
report.mdcites. - Repo and live agree on every field both expose.
DATA_REPO_VS_LIVE_DRIFThas zero rows, or each row is listed with its source. - No proposed SKU duplicates an existing SKU (
jq -r '.products[].variants[].sku' catalog.json | sort | uniq -dprints nothing). - For a regulated catalog, a keyword scan of
audit.csv,report.mdand the script returns zero hits on the banned-claims list. - Re-fetching one
sourceURL from the CSV still matches the recorded value.